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" 17b01430a0SFangrui Song #include "InputFiles.h" 182ec34544SRui Ueyama #include "LinkerScript.h" 192ec34544SRui Ueyama #include "OutputSections.h" 202ec34544SRui Ueyama #include "ScriptLexer.h" 2127bb7990SFangrui Song #include "SymbolTable.h" 222ec34544SRui Ueyama #include "Symbols.h" 232ec34544SRui Ueyama #include "Target.h" 2483d59e05SAlexandre Ganea #include "lld/Common/CommonLinkerContext.h" 252ec34544SRui Ueyama #include "llvm/ADT/SmallString.h" 262ec34544SRui Ueyama #include "llvm/ADT/StringRef.h" 270440be4aSRui Ueyama #include "llvm/ADT/StringSet.h" 282ec34544SRui Ueyama #include "llvm/ADT/StringSwitch.h" 29264b5d9eSZachary Turner #include "llvm/BinaryFormat/ELF.h" 302ec34544SRui Ueyama #include "llvm/Support/Casting.h" 312ec34544SRui Ueyama #include "llvm/Support/ErrorHandling.h" 322ec34544SRui Ueyama #include "llvm/Support/FileSystem.h" 33fa1145a8SIsaac Richter #include "llvm/Support/MathExtras.h" 342ec34544SRui Ueyama #include "llvm/Support/Path.h" 35fe0de25bSFangrui Song #include "llvm/Support/SaveAndRestore.h" 36439341b9SJames Henderson #include "llvm/Support/TimeProfiler.h" 372ec34544SRui Ueyama #include <cassert> 382ec34544SRui Ueyama #include <limits> 392ec34544SRui Ueyama #include <vector> 402ec34544SRui Ueyama 412ec34544SRui Ueyama using namespace llvm; 422ec34544SRui Ueyama using namespace llvm::ELF; 43b58079d4SRui Ueyama using namespace llvm::support::endian; 4407837b8fSFangrui Song using namespace lld; 4507837b8fSFangrui Song using namespace lld::elf; 462ec34544SRui Ueyama 4796b3fe02SRui Ueyama namespace { 4896b3fe02SRui Ueyama class ScriptParser final : ScriptLexer { 492ec34544SRui Ueyama public: 503837f427SRui Ueyama ScriptParser(MemoryBufferRef mb) : ScriptLexer(mb) { 5111ae59f0SRui Ueyama // Initialize IsUnderSysroot 523837f427SRui Ueyama if (config->sysroot == "") 5311ae59f0SRui Ueyama return; 543837f427SRui Ueyama StringRef path = mb.getBufferIdentifier(); 553837f427SRui Ueyama for (; !path.empty(); path = sys::path::parent_path(path)) { 563837f427SRui Ueyama if (!sys::fs::equivalent(config->sysroot, path)) 5711ae59f0SRui Ueyama continue; 583837f427SRui Ueyama isUnderSysroot = true; 5911ae59f0SRui Ueyama return; 6011ae59f0SRui Ueyama } 6111ae59f0SRui Ueyama } 622ec34544SRui Ueyama 632ec34544SRui Ueyama void readLinkerScript(); 642ec34544SRui Ueyama void readVersionScript(); 652ec34544SRui Ueyama void readDynamicList(); 663837f427SRui Ueyama void readDefsym(StringRef name); 672ec34544SRui Ueyama 682ec34544SRui Ueyama private: 693837f427SRui Ueyama void addFile(StringRef path); 702ec34544SRui Ueyama 712ec34544SRui Ueyama void readAsNeeded(); 722ec34544SRui Ueyama void readEntry(); 732ec34544SRui Ueyama void readExtern(); 742ec34544SRui Ueyama void readGroup(); 752ec34544SRui Ueyama void readInclude(); 761d92aa73SRui Ueyama void readInput(); 772ec34544SRui Ueyama void readMemory(); 782ec34544SRui Ueyama void readOutput(); 792ec34544SRui Ueyama void readOutputArch(); 802ec34544SRui Ueyama void readOutputFormat(); 81899fdf54SFangrui Song void readOverwriteSections(); 822ec34544SRui Ueyama void readPhdrs(); 835f37541cSGeorge Rimar void readRegionAlias(); 842ec34544SRui Ueyama void readSearchDir(); 852ec34544SRui Ueyama void readSections(); 86e262bb1aSRui Ueyama void readTarget(); 872ec34544SRui Ueyama void readVersion(); 882ec34544SRui Ueyama void readVersionScriptCommand(); 892ec34544SRui Ueyama 903837f427SRui Ueyama SymbolAssignment *readSymbolAssignment(StringRef name); 913837f427SRui Ueyama ByteCommand *readByteCommand(StringRef tok); 92b0486051SSimon Atanasyan std::array<uint8_t, 4> readFill(); 933837f427SRui Ueyama bool readSectionDirective(OutputSection *cmd, StringRef tok1, StringRef tok2); 943837f427SRui Ueyama void readSectionAddressType(OutputSection *cmd); 956c814931SFangrui Song OutputDesc *readOverlaySectionDescription(); 966c814931SFangrui Song OutputDesc *readOutputSectionDescription(StringRef outSec); 9764038ef8SFangrui Song SmallVector<SectionCommand *, 0> readOverlay(); 98a1c2ee01SFangrui Song SmallVector<StringRef, 0> readOutputSectionPhdrs(); 99dbd0ad33SPeter Smith std::pair<uint64_t, uint64_t> readInputSectionFlags(); 1003837f427SRui Ueyama InputSectionDescription *readInputSectionDescription(StringRef tok); 1012ec34544SRui Ueyama StringMatcher readFilePatterns(); 10264038ef8SFangrui Song SmallVector<SectionPattern, 0> readInputSectionsList(); 103dbd0ad33SPeter Smith InputSectionDescription *readInputSectionRules(StringRef filePattern, 104dbd0ad33SPeter Smith uint64_t withFlags, 105dbd0ad33SPeter Smith uint64_t withoutFlags); 1062ec34544SRui Ueyama unsigned readPhdrType(); 1072a9aed0eSFangrui Song SortSectionPolicy peekSortKind(); 1082ec34544SRui Ueyama SortSectionPolicy readSortKind(); 1093837f427SRui Ueyama SymbolAssignment *readProvideHidden(bool provide, bool hidden); 1103837f427SRui Ueyama SymbolAssignment *readAssignment(StringRef tok); 1112ec34544SRui Ueyama void readSort(); 112d30a78b3SGeorge Rimar Expr readAssert(); 1135fb17128SGeorge Rimar Expr readConstant(); 1145fb17128SGeorge Rimar Expr getPageSize(); 1152ec34544SRui Ueyama 11692b5b980SFangrui Song Expr readMemoryAssignment(StringRef, StringRef, StringRef); 1178cdf1c1eSIgor Kudrin void readMemoryAttributes(uint32_t &flags, uint32_t &invFlags, 1188cdf1c1eSIgor Kudrin uint32_t &negFlags, uint32_t &negInvFlags); 1192ec34544SRui Ueyama 1203837f427SRui Ueyama Expr combine(StringRef op, Expr l, Expr r); 1212ec34544SRui Ueyama Expr readExpr(); 1223837f427SRui Ueyama Expr readExpr1(Expr lhs, int minPrec); 1232ec34544SRui Ueyama StringRef readParenLiteral(); 1242ec34544SRui Ueyama Expr readPrimary(); 1253837f427SRui Ueyama Expr readTernary(Expr cond); 1262ec34544SRui Ueyama Expr readParenExpr(); 1272ec34544SRui Ueyama 1282ec34544SRui Ueyama // For parsing version script. 12964038ef8SFangrui Song SmallVector<SymbolVersion, 0> readVersionExtern(); 1302ec34544SRui Ueyama void readAnonymousDeclaration(); 1313837f427SRui Ueyama void readVersionDeclaration(StringRef verStr); 1322ec34544SRui Ueyama 13364038ef8SFangrui Song std::pair<SmallVector<SymbolVersion, 0>, SmallVector<SymbolVersion, 0>> 1342ec34544SRui Ueyama readSymbols(); 1352ec34544SRui Ueyama 136bf6e259bSFangrui Song // True if a script being read is in the --sysroot directory. 1373837f427SRui Ueyama bool isUnderSysroot = false; 1380440be4aSRui Ueyama 1395a44980fSFangrui Song bool seenDataAlign = false; 1405a44980fSFangrui Song bool seenRelroEnd = false; 1415a44980fSFangrui Song 1420440be4aSRui Ueyama // A set to detect an INCLUDE() cycle. 1433837f427SRui Ueyama StringSet<> seen; 1442ec34544SRui Ueyama }; 14596b3fe02SRui Ueyama } // namespace 1462ec34544SRui Ueyama 1473837f427SRui Ueyama static StringRef unquote(StringRef s) { 1483837f427SRui Ueyama if (s.startswith("\"")) 1493837f427SRui Ueyama return s.substr(1, s.size() - 2); 1503837f427SRui Ueyama return s; 1511e77ad14SRui Ueyama } 1521e77ad14SRui Ueyama 1532ec34544SRui Ueyama // Some operations only support one non absolute value. Move the 1542ec34544SRui Ueyama // absolute one to the right hand side for convenience. 1553837f427SRui Ueyama static void moveAbsRight(ExprValue &a, ExprValue &b) { 1563837f427SRui Ueyama if (a.sec == nullptr || (a.forceAbsolute && !b.isAbsolute())) 1573837f427SRui Ueyama std::swap(a, b); 1583837f427SRui Ueyama if (!b.isAbsolute()) 1593837f427SRui Ueyama error(a.loc + ": at least one side of the expression must be absolute"); 1602ec34544SRui Ueyama } 1612ec34544SRui Ueyama 1623837f427SRui Ueyama static ExprValue add(ExprValue a, ExprValue b) { 1633837f427SRui Ueyama moveAbsRight(a, b); 1643837f427SRui Ueyama return {a.sec, a.forceAbsolute, a.getSectionOffset() + b.getValue(), a.loc}; 1652ec34544SRui Ueyama } 1662ec34544SRui Ueyama 1673837f427SRui Ueyama static ExprValue sub(ExprValue a, ExprValue b) { 16863a4a98eSRafael Espindola // The distance between two symbols in sections is absolute. 1693837f427SRui Ueyama if (!a.isAbsolute() && !b.isAbsolute()) 1703837f427SRui Ueyama return a.getValue() - b.getValue(); 1713837f427SRui Ueyama return {a.sec, false, a.getSectionOffset() - b.getValue(), a.loc}; 1722ec34544SRui Ueyama } 1732ec34544SRui Ueyama 1743837f427SRui Ueyama static ExprValue bitAnd(ExprValue a, ExprValue b) { 1753837f427SRui Ueyama moveAbsRight(a, b); 1763837f427SRui Ueyama return {a.sec, a.forceAbsolute, 1773837f427SRui Ueyama (a.getValue() & b.getValue()) - a.getSecAddr(), a.loc}; 1782ec34544SRui Ueyama } 1792ec34544SRui Ueyama 1803837f427SRui Ueyama static ExprValue bitOr(ExprValue a, ExprValue b) { 1813837f427SRui Ueyama moveAbsRight(a, b); 1823837f427SRui Ueyama return {a.sec, a.forceAbsolute, 1833837f427SRui Ueyama (a.getValue() | b.getValue()) - a.getSecAddr(), a.loc}; 1842ec34544SRui Ueyama } 1852ec34544SRui Ueyama 1862ec34544SRui Ueyama void ScriptParser::readDynamicList() { 1872ec34544SRui Ueyama expect("{"); 18864038ef8SFangrui Song SmallVector<SymbolVersion, 0> locals; 18964038ef8SFangrui Song SmallVector<SymbolVersion, 0> globals; 1903837f427SRui Ueyama std::tie(locals, globals) = readSymbols(); 191d72d97b3SRafael Espindola expect(";"); 192d72d97b3SRafael Espindola 193d72d97b3SRafael Espindola if (!atEOF()) { 1942ec34544SRui Ueyama setError("EOF expected, but got " + next()); 195d72d97b3SRafael Espindola return; 196d72d97b3SRafael Espindola } 1973837f427SRui Ueyama if (!locals.empty()) { 198d72d97b3SRafael Espindola setError("\"local:\" scope not supported in --dynamic-list"); 199d72d97b3SRafael Espindola return; 200d72d97b3SRafael Espindola } 201d72d97b3SRafael Espindola 2023837f427SRui Ueyama for (SymbolVersion v : globals) 2033837f427SRui Ueyama config->dynamicList.push_back(v); 2042ec34544SRui Ueyama } 2052ec34544SRui Ueyama 2062ec34544SRui Ueyama void ScriptParser::readVersionScript() { 2072ec34544SRui Ueyama readVersionScriptCommand(); 2082ec34544SRui Ueyama if (!atEOF()) 2092ec34544SRui Ueyama setError("EOF expected, but got " + next()); 2102ec34544SRui Ueyama } 2112ec34544SRui Ueyama 2122ec34544SRui Ueyama void ScriptParser::readVersionScriptCommand() { 2132ec34544SRui Ueyama if (consume("{")) { 2142ec34544SRui Ueyama readAnonymousDeclaration(); 2152ec34544SRui Ueyama return; 2162ec34544SRui Ueyama } 2172ec34544SRui Ueyama 218b8a59c8aSBob Haarman while (!atEOF() && !errorCount() && peek() != "}") { 2193837f427SRui Ueyama StringRef verStr = next(); 2203837f427SRui Ueyama if (verStr == "{") { 2212ec34544SRui Ueyama setError("anonymous version definition is used in " 2222ec34544SRui Ueyama "combination with other version definitions"); 2232ec34544SRui Ueyama return; 2242ec34544SRui Ueyama } 2252ec34544SRui Ueyama expect("{"); 2263837f427SRui Ueyama readVersionDeclaration(verStr); 2272ec34544SRui Ueyama } 2282ec34544SRui Ueyama } 2292ec34544SRui Ueyama 2302ec34544SRui Ueyama void ScriptParser::readVersion() { 2312ec34544SRui Ueyama expect("{"); 2322ec34544SRui Ueyama readVersionScriptCommand(); 2332ec34544SRui Ueyama expect("}"); 2342ec34544SRui Ueyama } 2352ec34544SRui Ueyama 2362ec34544SRui Ueyama void ScriptParser::readLinkerScript() { 2372ec34544SRui Ueyama while (!atEOF()) { 2383837f427SRui Ueyama StringRef tok = next(); 2393837f427SRui Ueyama if (tok == ";") 2402ec34544SRui Ueyama continue; 2412ec34544SRui Ueyama 2423837f427SRui Ueyama if (tok == "ENTRY") { 2432ec34544SRui Ueyama readEntry(); 2443837f427SRui Ueyama } else if (tok == "EXTERN") { 2452ec34544SRui Ueyama readExtern(); 2463837f427SRui Ueyama } else if (tok == "GROUP") { 2472ec34544SRui Ueyama readGroup(); 2483837f427SRui Ueyama } else if (tok == "INCLUDE") { 2492ec34544SRui Ueyama readInclude(); 2503837f427SRui Ueyama } else if (tok == "INPUT") { 2511d92aa73SRui Ueyama readInput(); 2523837f427SRui Ueyama } else if (tok == "MEMORY") { 2532ec34544SRui Ueyama readMemory(); 2543837f427SRui Ueyama } else if (tok == "OUTPUT") { 2552ec34544SRui Ueyama readOutput(); 2563837f427SRui Ueyama } else if (tok == "OUTPUT_ARCH") { 2572ec34544SRui Ueyama readOutputArch(); 2583837f427SRui Ueyama } else if (tok == "OUTPUT_FORMAT") { 2592ec34544SRui Ueyama readOutputFormat(); 260899fdf54SFangrui Song } else if (tok == "OVERWRITE_SECTIONS") { 261899fdf54SFangrui Song readOverwriteSections(); 2623837f427SRui Ueyama } else if (tok == "PHDRS") { 2632ec34544SRui Ueyama readPhdrs(); 2643837f427SRui Ueyama } else if (tok == "REGION_ALIAS") { 2655f37541cSGeorge Rimar readRegionAlias(); 2663837f427SRui Ueyama } else if (tok == "SEARCH_DIR") { 2672ec34544SRui Ueyama readSearchDir(); 2683837f427SRui Ueyama } else if (tok == "SECTIONS") { 2692ec34544SRui Ueyama readSections(); 2703837f427SRui Ueyama } else if (tok == "TARGET") { 271e262bb1aSRui Ueyama readTarget(); 2723837f427SRui Ueyama } else if (tok == "VERSION") { 2732ec34544SRui Ueyama readVersion(); 2743837f427SRui Ueyama } else if (SymbolAssignment *cmd = readAssignment(tok)) { 2753837f427SRui Ueyama script->sectionCommands.push_back(cmd); 2762ec34544SRui Ueyama } else { 2773837f427SRui Ueyama setError("unknown directive: " + tok); 2782ec34544SRui Ueyama } 2792ec34544SRui Ueyama } 2802ec34544SRui Ueyama } 2812ec34544SRui Ueyama 2823837f427SRui Ueyama void ScriptParser::readDefsym(StringRef name) { 283c1522816SGeorge Rimar if (errorCount()) 284c1522816SGeorge Rimar return; 2853837f427SRui Ueyama Expr e = readExpr(); 2868c7e8cceSPetr Hosek if (!atEOF()) 2878c7e8cceSPetr Hosek setError("EOF expected, but got " + next()); 2883837f427SRui Ueyama SymbolAssignment *cmd = make<SymbolAssignment>(name, e, getCurrentLocation()); 2893837f427SRui Ueyama script->sectionCommands.push_back(cmd); 2908c7e8cceSPetr Hosek } 2918c7e8cceSPetr Hosek 2923837f427SRui Ueyama void ScriptParser::addFile(StringRef s) { 2933837f427SRui Ueyama if (isUnderSysroot && s.startswith("/")) { 2943837f427SRui Ueyama SmallString<128> pathData; 2953837f427SRui Ueyama StringRef path = (config->sysroot + s).toStringRef(pathData); 2962508733eSFangrui Song if (sys::fs::exists(path)) 29783d59e05SAlexandre Ganea driver->addFile(saver().save(path), /*withLOption=*/false); 2982508733eSFangrui Song else 2992508733eSFangrui Song setError("cannot find " + s + " inside " + config->sysroot); 3002ec34544SRui Ueyama return; 3012ec34544SRui Ueyama } 3022ec34544SRui Ueyama 3033837f427SRui Ueyama if (s.startswith("/")) { 304c384ca3cSFangrui Song // Case 1: s is an absolute path. Just open it. 30549a3ad21SRui Ueyama driver->addFile(s, /*withLOption=*/false); 3063837f427SRui Ueyama } else if (s.startswith("=")) { 307c384ca3cSFangrui Song // Case 2: relative to the sysroot. 3083837f427SRui Ueyama if (config->sysroot.empty()) 30949a3ad21SRui Ueyama driver->addFile(s.substr(1), /*withLOption=*/false); 3102ec34544SRui Ueyama else 31183d59e05SAlexandre Ganea driver->addFile(saver().save(config->sysroot + "/" + s.substr(1)), 31249a3ad21SRui Ueyama /*withLOption=*/false); 3133837f427SRui Ueyama } else if (s.startswith("-l")) { 314c384ca3cSFangrui Song // Case 3: search in the list of library paths. 3153837f427SRui Ueyama driver->addLibrary(s.substr(2)); 316c384ca3cSFangrui Song } else { 317c384ca3cSFangrui Song // Case 4: s is a relative path. Search in the directory of the script file. 318c384ca3cSFangrui Song std::string filename = std::string(getCurrentMB().getBufferIdentifier()); 319c384ca3cSFangrui Song StringRef directory = sys::path::parent_path(filename); 320c384ca3cSFangrui Song if (!directory.empty()) { 321c384ca3cSFangrui Song SmallString<0> path(directory); 322c384ca3cSFangrui Song sys::path::append(path, s); 323c384ca3cSFangrui Song if (sys::fs::exists(path)) { 324c384ca3cSFangrui Song driver->addFile(path, /*withLOption=*/false); 325c384ca3cSFangrui Song return; 326c384ca3cSFangrui Song } 327c384ca3cSFangrui Song } 328c384ca3cSFangrui Song // Then search in the current working directory. 329c384ca3cSFangrui Song if (sys::fs::exists(s)) { 33049a3ad21SRui Ueyama driver->addFile(s, /*withLOption=*/false); 3312ec34544SRui Ueyama } else { 332c384ca3cSFangrui Song // Finally, search in the list of library paths. 3333837f427SRui Ueyama if (Optional<std::string> path = findFromSearchPaths(s)) 33483d59e05SAlexandre Ganea driver->addFile(saver().save(*path), /*withLOption=*/true); 3352ec34544SRui Ueyama else 3363837f427SRui Ueyama setError("unable to find " + s); 3372ec34544SRui Ueyama } 3382ec34544SRui Ueyama } 339c384ca3cSFangrui Song } 3402ec34544SRui Ueyama 3412ec34544SRui Ueyama void ScriptParser::readAsNeeded() { 3422ec34544SRui Ueyama expect("("); 3433837f427SRui Ueyama bool orig = config->asNeeded; 3443837f427SRui Ueyama config->asNeeded = true; 345b8a59c8aSBob Haarman while (!errorCount() && !consume(")")) 3462ec34544SRui Ueyama addFile(unquote(next())); 3473837f427SRui Ueyama config->asNeeded = orig; 3482ec34544SRui Ueyama } 3492ec34544SRui Ueyama 3502ec34544SRui Ueyama void ScriptParser::readEntry() { 3512ec34544SRui Ueyama // -e <symbol> takes predecence over ENTRY(<symbol>). 3522ec34544SRui Ueyama expect("("); 3533837f427SRui Ueyama StringRef tok = next(); 3543837f427SRui Ueyama if (config->entry.empty()) 355363b2956SFangrui Song config->entry = unquote(tok); 3562ec34544SRui Ueyama expect(")"); 3572ec34544SRui Ueyama } 3582ec34544SRui Ueyama 3592ec34544SRui Ueyama void ScriptParser::readExtern() { 3602ec34544SRui Ueyama expect("("); 361b8a59c8aSBob Haarman while (!errorCount() && !consume(")")) 3623837f427SRui Ueyama config->undefined.push_back(unquote(next())); 3632ec34544SRui Ueyama } 3642ec34544SRui Ueyama 3652ec34544SRui Ueyama void ScriptParser::readGroup() { 3663837f427SRui Ueyama bool orig = InputFile::isInGroup; 3673837f427SRui Ueyama InputFile::isInGroup = true; 3681d92aa73SRui Ueyama readInput(); 3693837f427SRui Ueyama InputFile::isInGroup = orig; 3703837f427SRui Ueyama if (!orig) 3713837f427SRui Ueyama ++InputFile::nextGroupId; 3722ec34544SRui Ueyama } 3732ec34544SRui Ueyama 3742ec34544SRui Ueyama void ScriptParser::readInclude() { 3753837f427SRui Ueyama StringRef tok = unquote(next()); 3762ec34544SRui Ueyama 3773837f427SRui Ueyama if (!seen.insert(tok).second) { 3780440be4aSRui Ueyama setError("there is a cycle in linker script INCLUDEs"); 3790440be4aSRui Ueyama return; 3800440be4aSRui Ueyama } 3810440be4aSRui Ueyama 3823837f427SRui Ueyama if (Optional<std::string> path = searchScript(tok)) { 3833837f427SRui Ueyama if (Optional<MemoryBufferRef> mb = readFile(*path)) 3843837f427SRui Ueyama tokenize(*mb); 3852ec34544SRui Ueyama return; 3862ec34544SRui Ueyama } 3873837f427SRui Ueyama setError("cannot find linker script " + tok); 3882ec34544SRui Ueyama } 3892ec34544SRui Ueyama 3901d92aa73SRui Ueyama void ScriptParser::readInput() { 3911d92aa73SRui Ueyama expect("("); 3921d92aa73SRui Ueyama while (!errorCount() && !consume(")")) { 3931d92aa73SRui Ueyama if (consume("AS_NEEDED")) 3941d92aa73SRui Ueyama readAsNeeded(); 3951d92aa73SRui Ueyama else 3961d92aa73SRui Ueyama addFile(unquote(next())); 3971d92aa73SRui Ueyama } 3981d92aa73SRui Ueyama } 3991d92aa73SRui Ueyama 4002ec34544SRui Ueyama void ScriptParser::readOutput() { 4012ec34544SRui Ueyama // -o <file> takes predecence over OUTPUT(<file>). 4022ec34544SRui Ueyama expect("("); 4033837f427SRui Ueyama StringRef tok = next(); 4043837f427SRui Ueyama if (config->outputFile.empty()) 4053837f427SRui Ueyama config->outputFile = unquote(tok); 4062ec34544SRui Ueyama expect(")"); 4072ec34544SRui Ueyama } 4082ec34544SRui Ueyama 4092ec34544SRui Ueyama void ScriptParser::readOutputArch() { 4102ec34544SRui Ueyama // OUTPUT_ARCH is ignored for now. 4112ec34544SRui Ueyama expect("("); 412b8a59c8aSBob Haarman while (!errorCount() && !consume(")")) 4132ec34544SRui Ueyama skip(); 4142ec34544SRui Ueyama } 4152ec34544SRui Ueyama 4163837f427SRui Ueyama static std::pair<ELFKind, uint16_t> parseBfdName(StringRef s) { 4173837f427SRui Ueyama return StringSwitch<std::pair<ELFKind, uint16_t>>(s) 4184f8c8228SRui Ueyama .Case("elf32-i386", {ELF32LEKind, EM_386}) 4198527f32fSBen Shi .Case("elf32-avr", {ELF32LEKind, EM_AVR}) 4204f8c8228SRui Ueyama .Case("elf32-iamcu", {ELF32LEKind, EM_IAMCU}) 4214f8c8228SRui Ueyama .Case("elf32-littlearm", {ELF32LEKind, EM_ARM}) 4224f8c8228SRui Ueyama .Case("elf32-x86-64", {ELF32LEKind, EM_X86_64}) 42319b134ccSDimitry Andric .Case("elf64-aarch64", {ELF64LEKind, EM_AARCH64}) 4244f8c8228SRui Ueyama .Case("elf64-littleaarch64", {ELF64LEKind, EM_AARCH64}) 4257605a9a0SFangrui Song .Case("elf64-bigaarch64", {ELF64BEKind, EM_AARCH64}) 4264134143cSRui Ueyama .Case("elf32-powerpc", {ELF32BEKind, EM_PPC}) 427275eb828SBrandon Bergren .Case("elf32-powerpcle", {ELF32LEKind, EM_PPC}) 4284f8c8228SRui Ueyama .Case("elf64-powerpc", {ELF64BEKind, EM_PPC64}) 4294f8c8228SRui Ueyama .Case("elf64-powerpcle", {ELF64LEKind, EM_PPC64}) 4304f8c8228SRui Ueyama .Case("elf64-x86-64", {ELF64LEKind, EM_X86_64}) 4314134143cSRui Ueyama .Cases("elf32-tradbigmips", "elf32-bigmips", {ELF32BEKind, EM_MIPS}) 4324f8c8228SRui Ueyama .Case("elf32-ntradbigmips", {ELF32BEKind, EM_MIPS}) 4334f8c8228SRui Ueyama .Case("elf32-tradlittlemips", {ELF32LEKind, EM_MIPS}) 4344f8c8228SRui Ueyama .Case("elf32-ntradlittlemips", {ELF32LEKind, EM_MIPS}) 4354f8c8228SRui Ueyama .Case("elf64-tradbigmips", {ELF64BEKind, EM_MIPS}) 4364f8c8228SRui Ueyama .Case("elf64-tradlittlemips", {ELF64LEKind, EM_MIPS}) 43744d908d7SFangrui Song .Case("elf32-littleriscv", {ELF32LEKind, EM_RISCV}) 43844d908d7SFangrui Song .Case("elf64-littleriscv", {ELF64LEKind, EM_RISCV}) 439aff950e9SLemonBoy .Case("elf64-sparc", {ELF64BEKind, EM_SPARCV9}) 44092c6141cSLemonBoy .Case("elf32-msp430", {ELF32LEKind, EM_MSP430}) 4414f8c8228SRui Ueyama .Default({ELFNoneKind, EM_NONE}); 442ea8cd00aSRui Ueyama } 443ea8cd00aSRui Ueyama 444eea34aaeSFangrui Song // Parse OUTPUT_FORMAT(bfdname) or OUTPUT_FORMAT(default, big, little). Choose 445eea34aaeSFangrui Song // big if -EB is specified, little if -EL is specified, or default if neither is 446eea34aaeSFangrui Song // specified. 4472ec34544SRui Ueyama void ScriptParser::readOutputFormat() { 4482ec34544SRui Ueyama expect("("); 449ea8cd00aSRui Ueyama 450eea34aaeSFangrui Song StringRef s; 4512822852fSShoaib Meenai config->bfdname = unquote(next()); 452eea34aaeSFangrui Song if (!consume(")")) { 453eea34aaeSFangrui Song expect(","); 454eea34aaeSFangrui Song s = unquote(next()); 455eea34aaeSFangrui Song if (config->optEB) 456eea34aaeSFangrui Song config->bfdname = s; 457eea34aaeSFangrui Song expect(","); 458eea34aaeSFangrui Song s = unquote(next()); 459eea34aaeSFangrui Song if (config->optEL) 460eea34aaeSFangrui Song config->bfdname = s; 461eea34aaeSFangrui Song consume(")"); 462eea34aaeSFangrui Song } 463eea34aaeSFangrui Song s = config->bfdname; 4643837f427SRui Ueyama if (s.consume_back("-freebsd")) 4653837f427SRui Ueyama config->osabi = ELFOSABI_FREEBSD; 4664f8c8228SRui Ueyama 4673837f427SRui Ueyama std::tie(config->ekind, config->emachine) = parseBfdName(s); 4683837f427SRui Ueyama if (config->emachine == EM_NONE) 4692822852fSShoaib Meenai setError("unknown output format name: " + config->bfdname); 4703837f427SRui Ueyama if (s == "elf32-ntradlittlemips" || s == "elf32-ntradbigmips") 4713837f427SRui Ueyama config->mipsN32Abi = true; 47292c6141cSLemonBoy if (config->emachine == EM_MSP430) 47392c6141cSLemonBoy config->osabi = ELFOSABI_STANDALONE; 4742ec34544SRui Ueyama } 4752ec34544SRui Ueyama 4762ec34544SRui Ueyama void ScriptParser::readPhdrs() { 4772ec34544SRui Ueyama expect("{"); 4782ec34544SRui Ueyama 479b8a59c8aSBob Haarman while (!errorCount() && !consume("}")) { 4803837f427SRui Ueyama PhdrsCommand cmd; 4813837f427SRui Ueyama cmd.name = next(); 4823837f427SRui Ueyama cmd.type = readPhdrType(); 483b579c439SRui Ueyama 484b8a59c8aSBob Haarman while (!errorCount() && !consume(";")) { 485b579c439SRui Ueyama if (consume("FILEHDR")) 4863837f427SRui Ueyama cmd.hasFilehdr = true; 487b579c439SRui Ueyama else if (consume("PHDRS")) 4883837f427SRui Ueyama cmd.hasPhdrs = true; 489b579c439SRui Ueyama else if (consume("AT")) 4903837f427SRui Ueyama cmd.lmaExpr = readParenExpr(); 491b579c439SRui Ueyama else if (consume("FLAGS")) 4923837f427SRui Ueyama cmd.flags = readParenExpr()().getValue(); 493b579c439SRui Ueyama else 494b579c439SRui Ueyama setError("unexpected header attribute: " + next()); 495b579c439SRui Ueyama } 4960ae2c24cSRui Ueyama 4973837f427SRui Ueyama script->phdrsCommands.push_back(cmd); 4982ec34544SRui Ueyama } 4992ec34544SRui Ueyama } 5002ec34544SRui Ueyama 5015f37541cSGeorge Rimar void ScriptParser::readRegionAlias() { 5025f37541cSGeorge Rimar expect("("); 5033837f427SRui Ueyama StringRef alias = unquote(next()); 5045f37541cSGeorge Rimar expect(","); 5053837f427SRui Ueyama StringRef name = next(); 5065f37541cSGeorge Rimar expect(")"); 5075f37541cSGeorge Rimar 5083837f427SRui Ueyama if (script->memoryRegions.count(alias)) 5093837f427SRui Ueyama setError("redefinition of memory region '" + alias + "'"); 5103837f427SRui Ueyama if (!script->memoryRegions.count(name)) 5113837f427SRui Ueyama setError("memory region '" + name + "' is not defined"); 5123837f427SRui Ueyama script->memoryRegions.insert({alias, script->memoryRegions[name]}); 5135f37541cSGeorge Rimar } 5145f37541cSGeorge Rimar 5152ec34544SRui Ueyama void ScriptParser::readSearchDir() { 5162ec34544SRui Ueyama expect("("); 5173837f427SRui Ueyama StringRef tok = next(); 5183837f427SRui Ueyama if (!config->nostdlib) 5193837f427SRui Ueyama config->searchPaths.push_back(unquote(tok)); 5202ec34544SRui Ueyama expect(")"); 5212ec34544SRui Ueyama } 5222ec34544SRui Ueyama 523a582419aSGeorge Rimar // This reads an overlay description. Overlays are used to describe output 524a582419aSGeorge Rimar // sections that use the same virtual memory range and normally would trigger 525a582419aSGeorge Rimar // linker's sections sanity check failures. 526a582419aSGeorge Rimar // https://sourceware.org/binutils/docs/ld/Overlay-Description.html#Overlay-Description 52764038ef8SFangrui Song SmallVector<SectionCommand *, 0> ScriptParser::readOverlay() { 528a582419aSGeorge Rimar // VA and LMA expressions are optional, though for simplicity of 529a582419aSGeorge Rimar // implementation we assume they are not. That is what OVERLAY was designed 530a582419aSGeorge Rimar // for first of all: to allow sections with overlapping VAs at different LMAs. 5313837f427SRui Ueyama Expr addrExpr = readExpr(); 532a582419aSGeorge Rimar expect(":"); 533a582419aSGeorge Rimar expect("AT"); 5343837f427SRui Ueyama Expr lmaExpr = readParenExpr(); 535a582419aSGeorge Rimar expect("{"); 536a582419aSGeorge Rimar 53764038ef8SFangrui Song SmallVector<SectionCommand *, 0> v; 5383837f427SRui Ueyama OutputSection *prev = nullptr; 539a582419aSGeorge Rimar while (!errorCount() && !consume("}")) { 540a582419aSGeorge Rimar // VA is the same for all sections. The LMAs are consecutive in memory 541a582419aSGeorge Rimar // starting from the base load address specified. 5426c814931SFangrui Song OutputDesc *osd = readOverlaySectionDescription(); 5436c814931SFangrui Song osd->osec.addrExpr = addrExpr; 5443837f427SRui Ueyama if (prev) 5456c814931SFangrui Song osd->osec.lmaExpr = [=] { return prev->getLMA() + prev->size; }; 546a582419aSGeorge Rimar else 5476c814931SFangrui Song osd->osec.lmaExpr = lmaExpr; 5486c814931SFangrui Song v.push_back(osd); 5496c814931SFangrui Song prev = &osd->osec; 550a582419aSGeorge Rimar } 551a582419aSGeorge Rimar 552a582419aSGeorge Rimar // According to the specification, at the end of the overlay, the location 553a582419aSGeorge Rimar // counter should be equal to the overlay base address plus size of the 554a582419aSGeorge Rimar // largest section seen in the overlay. 555a582419aSGeorge Rimar // Here we want to create the Dot assignment command to achieve that. 5563837f427SRui Ueyama Expr moveDot = [=] { 5573837f427SRui Ueyama uint64_t max = 0; 5587051aeefSFangrui Song for (SectionCommand *cmd : v) 5596c814931SFangrui Song max = std::max(max, cast<OutputDesc>(cmd)->osec.size); 5603837f427SRui Ueyama return addrExpr().getValue() + max; 561a582419aSGeorge Rimar }; 5623837f427SRui Ueyama v.push_back(make<SymbolAssignment>(".", moveDot, getCurrentLocation())); 5633837f427SRui Ueyama return v; 564a582419aSGeorge Rimar } 565a582419aSGeorge Rimar 566899fdf54SFangrui Song void ScriptParser::readOverwriteSections() { 567899fdf54SFangrui Song expect("{"); 568899fdf54SFangrui Song while (!errorCount() && !consume("}")) 569899fdf54SFangrui Song script->overwriteSections.push_back(readOutputSectionDescription(next())); 570899fdf54SFangrui Song } 571899fdf54SFangrui Song 5722ec34544SRui Ueyama void ScriptParser::readSections() { 5732ec34544SRui Ueyama expect("{"); 57464038ef8SFangrui Song SmallVector<SectionCommand *, 0> v; 575b8a59c8aSBob Haarman while (!errorCount() && !consume("}")) { 5763837f427SRui Ueyama StringRef tok = next(); 5773837f427SRui Ueyama if (tok == "OVERLAY") { 5787051aeefSFangrui Song for (SectionCommand *cmd : readOverlay()) 5793837f427SRui Ueyama v.push_back(cmd); 580a582419aSGeorge Rimar continue; 5813837f427SRui Ueyama } else if (tok == "INCLUDE") { 5822e9d40d5SRui Ueyama readInclude(); 5832e9d40d5SRui Ueyama continue; 584a582419aSGeorge Rimar } 585a582419aSGeorge Rimar 5867051aeefSFangrui Song if (SectionCommand *cmd = readAssignment(tok)) 5873837f427SRui Ueyama v.push_back(cmd); 588d30a78b3SGeorge Rimar else 5893837f427SRui Ueyama v.push_back(readOutputSectionDescription(tok)); 5902ec34544SRui Ueyama } 5915a44980fSFangrui Song 5925a44980fSFangrui Song // If DATA_SEGMENT_RELRO_END is absent, for sections after DATA_SEGMENT_ALIGN, 5935a44980fSFangrui Song // the relro fields should be cleared. 5945a44980fSFangrui Song if (!seenRelroEnd) 5955a44980fSFangrui Song for (SectionCommand *cmd : v) 5965a44980fSFangrui Song if (auto *osd = dyn_cast<OutputDesc>(cmd)) 5975a44980fSFangrui Song osd->osec.relro = false; 5985a44980fSFangrui Song 5997c426fb1SFangrui Song script->sectionCommands.insert(script->sectionCommands.end(), v.begin(), 6007c426fb1SFangrui Song v.end()); 6019e2c8a9dSGeorge Rimar 6027c426fb1SFangrui Song if (atEOF() || !consume("INSERT")) { 6037c426fb1SFangrui Song script->hasSectionsCommand = true; 6049e2c8a9dSGeorge Rimar return; 6059e2c8a9dSGeorge Rimar } 6069e2c8a9dSGeorge Rimar 6077c426fb1SFangrui Song bool isAfter = false; 6087c426fb1SFangrui Song if (consume("AFTER")) 6097c426fb1SFangrui Song isAfter = true; 6107c426fb1SFangrui Song else if (!consume("BEFORE")) 6117c426fb1SFangrui Song setError("expected AFTER/BEFORE, but got '" + next() + "'"); 6127c426fb1SFangrui Song StringRef where = next(); 613a1c2ee01SFangrui Song SmallVector<StringRef, 0> names; 6147051aeefSFangrui Song for (SectionCommand *cmd : v) 6156c814931SFangrui Song if (auto *os = dyn_cast<OutputDesc>(cmd)) 6166c814931SFangrui Song names.push_back(os->osec.name); 61703051f7aSFangrui Song if (!names.empty()) 61803051f7aSFangrui Song script->insertCommands.push_back({std::move(names), isAfter, where}); 6192ec34544SRui Ueyama } 6202ec34544SRui Ueyama 621e262bb1aSRui Ueyama void ScriptParser::readTarget() { 622e262bb1aSRui Ueyama // TARGET(foo) is an alias for "--format foo". Unlike GNU linkers, 623e262bb1aSRui Ueyama // we accept only a limited set of BFD names (i.e. "elf" or "binary") 624e262bb1aSRui Ueyama // for --format. We recognize only /^elf/ and "binary" in the linker 625e262bb1aSRui Ueyama // script as well. 626e262bb1aSRui Ueyama expect("("); 6274cb05dc3SFangrui Song StringRef tok = unquote(next()); 628e262bb1aSRui Ueyama expect(")"); 629e262bb1aSRui Ueyama 6303837f427SRui Ueyama if (tok.startswith("elf")) 6313837f427SRui Ueyama config->formatBinary = false; 6323837f427SRui Ueyama else if (tok == "binary") 6333837f427SRui Ueyama config->formatBinary = true; 634e262bb1aSRui Ueyama else 6353837f427SRui Ueyama setError("unknown target: " + tok); 636e262bb1aSRui Ueyama } 637e262bb1aSRui Ueyama 6383837f427SRui Ueyama static int precedence(StringRef op) { 6393837f427SRui Ueyama return StringSwitch<int>(op) 640d479b2e4SFangrui Song .Cases("*", "/", "%", 10) 641d479b2e4SFangrui Song .Cases("+", "-", 9) 642d479b2e4SFangrui Song .Cases("<<", ">>", 8) 643d479b2e4SFangrui Song .Cases("<", "<=", ">", ">=", 7) 644d479b2e4SFangrui Song .Cases("==", "!=", 6) 645d479b2e4SFangrui Song .Case("&", 5) 646d479b2e4SFangrui Song .Case("|", 4) 647d479b2e4SFangrui Song .Case("&&", 3) 648d479b2e4SFangrui Song .Case("||", 2) 649b0d6dd39SFangrui Song .Case("?", 1) 6502ec34544SRui Ueyama .Default(-1); 6512ec34544SRui Ueyama } 6522ec34544SRui Ueyama 6532ec34544SRui Ueyama StringMatcher ScriptParser::readFilePatterns() { 654c42fe247SThomas Preud'homme StringMatcher Matcher; 655c42fe247SThomas Preud'homme 656b8a59c8aSBob Haarman while (!errorCount() && !consume(")")) 657c42fe247SThomas Preud'homme Matcher.addPattern(SingleStringMatcher(next())); 658c42fe247SThomas Preud'homme return Matcher; 6592ec34544SRui Ueyama } 6602ec34544SRui Ueyama 6612a9aed0eSFangrui Song SortSectionPolicy ScriptParser::peekSortKind() { 6622a9aed0eSFangrui Song return StringSwitch<SortSectionPolicy>(peek()) 6632a9aed0eSFangrui Song .Cases("SORT", "SORT_BY_NAME", SortSectionPolicy::Name) 6642a9aed0eSFangrui Song .Case("SORT_BY_ALIGNMENT", SortSectionPolicy::Alignment) 6652a9aed0eSFangrui Song .Case("SORT_BY_INIT_PRIORITY", SortSectionPolicy::Priority) 6662a9aed0eSFangrui Song .Case("SORT_NONE", SortSectionPolicy::None) 6672a9aed0eSFangrui Song .Default(SortSectionPolicy::Default); 6682a9aed0eSFangrui Song } 6692a9aed0eSFangrui Song 6702ec34544SRui Ueyama SortSectionPolicy ScriptParser::readSortKind() { 6712a9aed0eSFangrui Song SortSectionPolicy ret = peekSortKind(); 6722a9aed0eSFangrui Song if (ret != SortSectionPolicy::Default) 6732a9aed0eSFangrui Song skip(); 6742a9aed0eSFangrui Song return ret; 6752ec34544SRui Ueyama } 6762ec34544SRui Ueyama 67703fc8d1eSRui Ueyama // Reads SECTIONS command contents in the following form: 67803fc8d1eSRui Ueyama // 67903fc8d1eSRui Ueyama // <contents> ::= <elem>* 68003fc8d1eSRui Ueyama // <elem> ::= <exclude>? <glob-pattern> 68103fc8d1eSRui Ueyama // <exclude> ::= "EXCLUDE_FILE" "(" <glob-pattern>+ ")" 68203fc8d1eSRui Ueyama // 68303fc8d1eSRui Ueyama // For example, 68403fc8d1eSRui Ueyama // 68503fc8d1eSRui Ueyama // *(.foo EXCLUDE_FILE (a.o) .bar EXCLUDE_FILE (b.o) .baz) 68603fc8d1eSRui Ueyama // 68703fc8d1eSRui Ueyama // is parsed as ".foo", ".bar" with "a.o", and ".baz" with "b.o". 68803fc8d1eSRui Ueyama // The semantics of that is section .foo in any file, section .bar in 68903fc8d1eSRui Ueyama // any file but a.o, and section .baz in any file but b.o. 69064038ef8SFangrui Song SmallVector<SectionPattern, 0> ScriptParser::readInputSectionsList() { 69164038ef8SFangrui Song SmallVector<SectionPattern, 0> ret; 692b8a59c8aSBob Haarman while (!errorCount() && peek() != ")") { 6933837f427SRui Ueyama StringMatcher excludeFilePat; 6942ec34544SRui Ueyama if (consume("EXCLUDE_FILE")) { 6952ec34544SRui Ueyama expect("("); 6963837f427SRui Ueyama excludeFilePat = readFilePatterns(); 6972ec34544SRui Ueyama } 6982ec34544SRui Ueyama 699c42fe247SThomas Preud'homme StringMatcher SectionMatcher; 7002a9aed0eSFangrui Song // Break if the next token is ), EXCLUDE_FILE, or SORT*. 7012a9aed0eSFangrui Song while (!errorCount() && peek() != ")" && peek() != "EXCLUDE_FILE" && 7022a9aed0eSFangrui Song peekSortKind() == SortSectionPolicy::Default) 703c42fe247SThomas Preud'homme SectionMatcher.addPattern(unquote(next())); 7042ec34544SRui Ueyama 705c42fe247SThomas Preud'homme if (!SectionMatcher.empty()) 706c42fe247SThomas Preud'homme ret.push_back({std::move(excludeFilePat), std::move(SectionMatcher)}); 7072a9aed0eSFangrui Song else if (excludeFilePat.empty()) 7082a9aed0eSFangrui Song break; 7092ec34544SRui Ueyama else 7102ec34544SRui Ueyama setError("section pattern is expected"); 7112ec34544SRui Ueyama } 7123837f427SRui Ueyama return ret; 7132ec34544SRui Ueyama } 7142ec34544SRui Ueyama 7152ec34544SRui Ueyama // Reads contents of "SECTIONS" directive. That directive contains a 7162ec34544SRui Ueyama // list of glob patterns for input sections. The grammar is as follows. 7172ec34544SRui Ueyama // 7182ec34544SRui Ueyama // <patterns> ::= <section-list> 7192ec34544SRui Ueyama // | <sort> "(" <section-list> ")" 7202ec34544SRui Ueyama // | <sort> "(" <sort> "(" <section-list> ")" ")" 7212ec34544SRui Ueyama // 7222ec34544SRui Ueyama // <sort> ::= "SORT" | "SORT_BY_NAME" | "SORT_BY_ALIGNMENT" 7232ec34544SRui Ueyama // | "SORT_BY_INIT_PRIORITY" | "SORT_NONE" 7242ec34544SRui Ueyama // 7252ec34544SRui Ueyama // <section-list> is parsed by readInputSectionsList(). 7262ec34544SRui Ueyama InputSectionDescription * 727dbd0ad33SPeter Smith ScriptParser::readInputSectionRules(StringRef filePattern, uint64_t withFlags, 728dbd0ad33SPeter Smith uint64_t withoutFlags) { 729dbd0ad33SPeter Smith auto *cmd = 730dbd0ad33SPeter Smith make<InputSectionDescription>(filePattern, withFlags, withoutFlags); 7312ec34544SRui Ueyama expect("("); 7322ec34544SRui Ueyama 733b8a59c8aSBob Haarman while (!errorCount() && !consume(")")) { 7343837f427SRui Ueyama SortSectionPolicy outer = readSortKind(); 7353837f427SRui Ueyama SortSectionPolicy inner = SortSectionPolicy::Default; 73664038ef8SFangrui Song SmallVector<SectionPattern, 0> v; 7373837f427SRui Ueyama if (outer != SortSectionPolicy::Default) { 7382ec34544SRui Ueyama expect("("); 7393837f427SRui Ueyama inner = readSortKind(); 7403837f427SRui Ueyama if (inner != SortSectionPolicy::Default) { 7412ec34544SRui Ueyama expect("("); 7423837f427SRui Ueyama v = readInputSectionsList(); 7432ec34544SRui Ueyama expect(")"); 7442ec34544SRui Ueyama } else { 7453837f427SRui Ueyama v = readInputSectionsList(); 7462ec34544SRui Ueyama } 7472ec34544SRui Ueyama expect(")"); 7482ec34544SRui Ueyama } else { 7493837f427SRui Ueyama v = readInputSectionsList(); 7502ec34544SRui Ueyama } 7512ec34544SRui Ueyama 7523837f427SRui Ueyama for (SectionPattern &pat : v) { 7533837f427SRui Ueyama pat.sortInner = inner; 7543837f427SRui Ueyama pat.sortOuter = outer; 7552ec34544SRui Ueyama } 7562ec34544SRui Ueyama 7573837f427SRui Ueyama std::move(v.begin(), v.end(), std::back_inserter(cmd->sectionPatterns)); 7582ec34544SRui Ueyama } 7593837f427SRui Ueyama return cmd; 7602ec34544SRui Ueyama } 7612ec34544SRui Ueyama 7622ec34544SRui Ueyama InputSectionDescription * 7633837f427SRui Ueyama ScriptParser::readInputSectionDescription(StringRef tok) { 7642ec34544SRui Ueyama // Input section wildcard can be surrounded by KEEP. 7652ec34544SRui Ueyama // https://sourceware.org/binutils/docs/ld/Input-Section-Keep.html#Input-Section-Keep 766dbd0ad33SPeter Smith uint64_t withFlags = 0; 767dbd0ad33SPeter Smith uint64_t withoutFlags = 0; 7683837f427SRui Ueyama if (tok == "KEEP") { 7692ec34544SRui Ueyama expect("("); 770dbd0ad33SPeter Smith if (consume("INPUT_SECTION_FLAGS")) 771dbd0ad33SPeter Smith std::tie(withFlags, withoutFlags) = readInputSectionFlags(); 772dbd0ad33SPeter Smith InputSectionDescription *cmd = 773dbd0ad33SPeter Smith readInputSectionRules(next(), withFlags, withoutFlags); 7742ec34544SRui Ueyama expect(")"); 7753837f427SRui Ueyama script->keptSections.push_back(cmd); 7763837f427SRui Ueyama return cmd; 7772ec34544SRui Ueyama } 778dbd0ad33SPeter Smith if (tok == "INPUT_SECTION_FLAGS") { 779dbd0ad33SPeter Smith std::tie(withFlags, withoutFlags) = readInputSectionFlags(); 780dbd0ad33SPeter Smith tok = next(); 781dbd0ad33SPeter Smith } 782dbd0ad33SPeter Smith return readInputSectionRules(tok, withFlags, withoutFlags); 7832ec34544SRui Ueyama } 7842ec34544SRui Ueyama 7852ec34544SRui Ueyama void ScriptParser::readSort() { 7862ec34544SRui Ueyama expect("("); 7872ec34544SRui Ueyama expect("CONSTRUCTORS"); 7882ec34544SRui Ueyama expect(")"); 7892ec34544SRui Ueyama } 7902ec34544SRui Ueyama 791d30a78b3SGeorge Rimar Expr ScriptParser::readAssert() { 7922ec34544SRui Ueyama expect("("); 7933837f427SRui Ueyama Expr e = readExpr(); 7942ec34544SRui Ueyama expect(","); 7953837f427SRui Ueyama StringRef msg = unquote(next()); 7962ec34544SRui Ueyama expect(")"); 797b579c439SRui Ueyama 7982ec34544SRui Ueyama return [=] { 7993837f427SRui Ueyama if (!e().getValue()) 8002682bc3cSFangrui Song errorOrWarn(msg); 8013837f427SRui Ueyama return script->getDot(); 8022ec34544SRui Ueyama }; 8032ec34544SRui Ueyama } 8042ec34544SRui Ueyama 80566f8ac8dSFangrui Song #define ECase(X) \ 80666f8ac8dSFangrui Song { #X, X } 80766f8ac8dSFangrui Song constexpr std::pair<const char *, unsigned> typeMap[] = { 80866f8ac8dSFangrui Song ECase(SHT_PROGBITS), ECase(SHT_NOTE), ECase(SHT_NOBITS), 80966f8ac8dSFangrui Song ECase(SHT_INIT_ARRAY), ECase(SHT_FINI_ARRAY), ECase(SHT_PREINIT_ARRAY), 81066f8ac8dSFangrui Song }; 81166f8ac8dSFangrui Song #undef ECase 81266f8ac8dSFangrui Song 813a46d08ebSGeorge Rimar // Tries to read the special directive for an output section definition which 81466f8ac8dSFangrui Song // can be one of following: "(NOLOAD)", "(COPY)", "(INFO)", "(OVERLAY)", and 81566f8ac8dSFangrui Song // "(TYPE=<value>)". 81666f8ac8dSFangrui Song // Tok1 and Tok2 are next 2 tokens peeked. See comment for 81766f8ac8dSFangrui Song // readSectionAddressType below. 8183837f427SRui Ueyama bool ScriptParser::readSectionDirective(OutputSection *cmd, StringRef tok1, StringRef tok2) { 8193837f427SRui Ueyama if (tok1 != "(") 820a46d08ebSGeorge Rimar return false; 82166f8ac8dSFangrui Song if (tok2 != "NOLOAD" && tok2 != "COPY" && tok2 != "INFO" && 82266f8ac8dSFangrui Song tok2 != "OVERLAY" && tok2 != "TYPE") 823a46d08ebSGeorge Rimar return false; 824a46d08ebSGeorge Rimar 825a46d08ebSGeorge Rimar expect("("); 826a46d08ebSGeorge Rimar if (consume("NOLOAD")) { 827fdc41aa2SMatt Schulte cmd->type = SHT_NOBITS; 82866f8ac8dSFangrui Song cmd->typeIsSet = true; 82966f8ac8dSFangrui Song } else if (consume("TYPE")) { 83066f8ac8dSFangrui Song expect("="); 83166f8ac8dSFangrui Song StringRef value = peek(); 83266f8ac8dSFangrui Song auto it = llvm::find_if(typeMap, [=](auto e) { return e.first == value; }); 83366f8ac8dSFangrui Song if (it != std::end(typeMap)) { 83466f8ac8dSFangrui Song // The value is a recognized literal SHT_*. 83566f8ac8dSFangrui Song cmd->type = it->second; 83666f8ac8dSFangrui Song skip(); 83766f8ac8dSFangrui Song } else if (value.startswith("SHT_")) { 83866f8ac8dSFangrui Song setError("unknown section type " + value); 83966f8ac8dSFangrui Song } else { 84066f8ac8dSFangrui Song // Otherwise, read an expression. 84166f8ac8dSFangrui Song cmd->type = readExpr()().getValue(); 84266f8ac8dSFangrui Song } 84366f8ac8dSFangrui Song cmd->typeIsSet = true; 844a46d08ebSGeorge Rimar } else { 845a46d08ebSGeorge Rimar skip(); // This is "COPY", "INFO" or "OVERLAY". 8463837f427SRui Ueyama cmd->nonAlloc = true; 847a46d08ebSGeorge Rimar } 848a46d08ebSGeorge Rimar expect(")"); 849a46d08ebSGeorge Rimar return true; 850a46d08ebSGeorge Rimar } 851a46d08ebSGeorge Rimar 8521c08e9f5SGeorge Rimar // Reads an expression and/or the special directive for an output 8531c08e9f5SGeorge Rimar // section definition. Directive is one of following: "(NOLOAD)", 8541c08e9f5SGeorge Rimar // "(COPY)", "(INFO)" or "(OVERLAY)". 8553271d370SRui Ueyama // 8563271d370SRui Ueyama // An output section name can be followed by an address expression 8571c08e9f5SGeorge Rimar // and/or directive. This grammar is not LL(1) because "(" can be 85897f4d158SGeorge Rimar // interpreted as either the beginning of some expression or beginning 8591c08e9f5SGeorge Rimar // of directive. 8603271d370SRui Ueyama // 861b579c439SRui Ueyama // https://sourceware.org/binutils/docs/ld/Output-Section-Address.html 862fbb0463fSGeorge Rimar // https://sourceware.org/binutils/docs/ld/Output-Section-Type.html 8633837f427SRui Ueyama void ScriptParser::readSectionAddressType(OutputSection *cmd) { 86466f8ac8dSFangrui Song // Temporarily set inExpr to support TYPE=<value> without spaces. 86566f8ac8dSFangrui Song bool saved = std::exchange(inExpr, true); 86666f8ac8dSFangrui Song bool isDirective = readSectionDirective(cmd, peek(), peek2()); 86766f8ac8dSFangrui Song inExpr = saved; 86866f8ac8dSFangrui Song if (isDirective) 8693271d370SRui Ueyama return; 8703271d370SRui Ueyama 8713837f427SRui Ueyama cmd->addrExpr = readExpr(); 8723837f427SRui Ueyama if (peek() == "(" && !readSectionDirective(cmd, "(", peek2())) 873a46d08ebSGeorge Rimar setError("unknown section directive: " + peek2()); 874fbb0463fSGeorge Rimar } 875fbb0463fSGeorge Rimar 8763837f427SRui Ueyama static Expr checkAlignment(Expr e, std::string &loc) { 877f22ec9ddSGeorge Rimar return [=] { 8783837f427SRui Ueyama uint64_t alignment = std::max((uint64_t)1, e().getValue()); 8793837f427SRui Ueyama if (!isPowerOf2_64(alignment)) { 8803837f427SRui Ueyama error(loc + ": alignment must be power of 2"); 881f22ec9ddSGeorge Rimar return (uint64_t)1; // Return a dummy value. 882f22ec9ddSGeorge Rimar } 8833837f427SRui Ueyama return alignment; 884f22ec9ddSGeorge Rimar }; 885f22ec9ddSGeorge Rimar } 886f22ec9ddSGeorge Rimar 8876c814931SFangrui Song OutputDesc *ScriptParser::readOverlaySectionDescription() { 8886c814931SFangrui Song OutputDesc *osd = script->createOutputSection(next(), getCurrentLocation()); 8896c814931SFangrui Song osd->osec.inOverlay = true; 890a582419aSGeorge Rimar expect("{"); 891dbd0ad33SPeter Smith while (!errorCount() && !consume("}")) { 892dbd0ad33SPeter Smith uint64_t withFlags = 0; 893dbd0ad33SPeter Smith uint64_t withoutFlags = 0; 894dbd0ad33SPeter Smith if (consume("INPUT_SECTION_FLAGS")) 895dbd0ad33SPeter Smith std::tie(withFlags, withoutFlags) = readInputSectionFlags(); 8966c814931SFangrui Song osd->osec.commands.push_back( 897dbd0ad33SPeter Smith readInputSectionRules(next(), withFlags, withoutFlags)); 898dbd0ad33SPeter Smith } 8996c814931SFangrui Song return osd; 900a582419aSGeorge Rimar } 901a582419aSGeorge Rimar 9026c814931SFangrui Song OutputDesc *ScriptParser::readOutputSectionDescription(StringRef outSec) { 9036c814931SFangrui Song OutputDesc *cmd = script->createOutputSection(outSec, getCurrentLocation()); 9046c814931SFangrui Song OutputSection *osec = &cmd->osec; 9055a44980fSFangrui Song // Maybe relro. Will reset to false if DATA_SEGMENT_RELRO_END is absent. 9065a44980fSFangrui Song osec->relro = seenDataAlign && !seenRelroEnd; 9073271d370SRui Ueyama 9083837f427SRui Ueyama size_t symbolsReferenced = script->referencedSymbols.size(); 909c4df670dSGeorge Rimar 9103271d370SRui Ueyama if (peek() != ":") 9116c814931SFangrui Song readSectionAddressType(osec); 9122ec34544SRui Ueyama expect(":"); 9132ec34544SRui Ueyama 9143837f427SRui Ueyama std::string location = getCurrentLocation(); 9152ec34544SRui Ueyama if (consume("AT")) 9166c814931SFangrui Song osec->lmaExpr = readParenExpr(); 9172ec34544SRui Ueyama if (consume("ALIGN")) 9186c814931SFangrui Song osec->alignExpr = checkAlignment(readParenExpr(), location); 9192ec34544SRui Ueyama if (consume("SUBALIGN")) 9206c814931SFangrui Song osec->subalignExpr = checkAlignment(readParenExpr(), location); 9212ec34544SRui Ueyama 9222ec34544SRui Ueyama // Parse constraints. 9232ec34544SRui Ueyama if (consume("ONLY_IF_RO")) 9246c814931SFangrui Song osec->constraint = ConstraintKind::ReadOnly; 9252ec34544SRui Ueyama if (consume("ONLY_IF_RW")) 9266c814931SFangrui Song osec->constraint = ConstraintKind::ReadWrite; 9272ec34544SRui Ueyama expect("{"); 9282ec34544SRui Ueyama 929b8a59c8aSBob Haarman while (!errorCount() && !consume("}")) { 9303837f427SRui Ueyama StringRef tok = next(); 9313837f427SRui Ueyama if (tok == ";") { 9322ec34544SRui Ueyama // Empty commands are allowed. Do nothing here. 9333837f427SRui Ueyama } else if (SymbolAssignment *assign = readAssignment(tok)) { 9346c814931SFangrui Song osec->commands.push_back(assign); 9353837f427SRui Ueyama } else if (ByteCommand *data = readByteCommand(tok)) { 9366c814931SFangrui Song osec->commands.push_back(data); 9373837f427SRui Ueyama } else if (tok == "CONSTRUCTORS") { 9382ec34544SRui Ueyama // CONSTRUCTORS is a keyword to make the linker recognize C++ ctors/dtors 9392ec34544SRui Ueyama // by name. This is for very old file formats such as ECOFF/XCOFF. 9402ec34544SRui Ueyama // For ELF, we should ignore. 9413837f427SRui Ueyama } else if (tok == "FILL") { 9420810f16fSGeorge Rimar // We handle the FILL command as an alias for =fillexp section attribute, 9430810f16fSGeorge Rimar // which is different from what GNU linkers do. 9440810f16fSGeorge Rimar // https://sourceware.org/binutils/docs/ld/Output-Section-Data.html 945bb7d2b17SGeorgii Rymar if (peek() != "(") 946bb7d2b17SGeorgii Rymar setError("( expected, but got " + peek()); 9476c814931SFangrui Song osec->filler = readFill(); 9483837f427SRui Ueyama } else if (tok == "SORT") { 9492ec34544SRui Ueyama readSort(); 9503837f427SRui Ueyama } else if (tok == "INCLUDE") { 9512e9d40d5SRui Ueyama readInclude(); 952177fd72fSFangrui Song } else if (tok == "(" || tok == ")") { 953177fd72fSFangrui Song setError("expected filename pattern"); 9542ec34544SRui Ueyama } else if (peek() == "(") { 9556c814931SFangrui Song osec->commands.push_back(readInputSectionDescription(tok)); 9562ec34544SRui Ueyama } else { 957f49fe218SGeorge Rimar // We have a file name and no input sections description. It is not a 958f49fe218SGeorge Rimar // commonly used syntax, but still acceptable. In that case, all sections 959f49fe218SGeorge Rimar // from the file will be included. 960dbd0ad33SPeter Smith // FIXME: GNU ld permits INPUT_SECTION_FLAGS to be used here. We do not 961dbd0ad33SPeter Smith // handle this case here as it will already have been matched by the 962dbd0ad33SPeter Smith // case above. 9633837f427SRui Ueyama auto *isd = make<InputSectionDescription>(tok); 964c42fe247SThomas Preud'homme isd->sectionPatterns.push_back({{}, StringMatcher("*")}); 9656c814931SFangrui Song osec->commands.push_back(isd); 9662ec34544SRui Ueyama } 9672ec34544SRui Ueyama } 9682ec34544SRui Ueyama 9692ec34544SRui Ueyama if (consume(">")) 9706c814931SFangrui Song osec->memoryRegionName = std::string(next()); 9712ec34544SRui Ueyama 9725d01a8beSGeorge Rimar if (consume("AT")) { 9735d01a8beSGeorge Rimar expect(">"); 9746c814931SFangrui Song osec->lmaRegionName = std::string(next()); 9755d01a8beSGeorge Rimar } 9765d01a8beSGeorge Rimar 9776c814931SFangrui Song if (osec->lmaExpr && !osec->lmaRegionName.empty()) 9785d01a8beSGeorge Rimar error("section can't have both LMA and a load region"); 9795d01a8beSGeorge Rimar 9806c814931SFangrui Song osec->phdrs = readOutputSectionPhdrs(); 9812ec34544SRui Ueyama 9820810f16fSGeorge Rimar if (peek() == "=" || peek().startswith("=")) { 9833837f427SRui Ueyama inExpr = true; 9840810f16fSGeorge Rimar consume("="); 9856c814931SFangrui Song osec->filler = readFill(); 9863837f427SRui Ueyama inExpr = false; 9870810f16fSGeorge Rimar } 9882ec34544SRui Ueyama 9892ec34544SRui Ueyama // Consume optional comma following output section command. 9902ec34544SRui Ueyama consume(","); 9912ec34544SRui Ueyama 9923837f427SRui Ueyama if (script->referencedSymbols.size() > symbolsReferenced) 9936c814931SFangrui Song osec->expressionsUseSymbols = true; 9943837f427SRui Ueyama return cmd; 9952ec34544SRui Ueyama } 9962ec34544SRui Ueyama 9970810f16fSGeorge Rimar // Reads a `=<fillexp>` expression and returns its value as a big-endian number. 9982ec34544SRui Ueyama // https://sourceware.org/binutils/docs/ld/Output-Section-Fill.html 9990810f16fSGeorge Rimar // We do not support using symbols in such expressions. 10002ec34544SRui Ueyama // 10018acbf1ccSRui Ueyama // When reading a hexstring, ld.bfd handles it as a blob of arbitrary 10028acbf1ccSRui Ueyama // size, while ld.gold always handles it as a 32-bit big-endian number. 10038acbf1ccSRui Ueyama // We are compatible with ld.gold because it's easier to implement. 1004bb7d2b17SGeorgii Rymar // Also, we require that expressions with operators must be wrapped into 1005bb7d2b17SGeorgii Rymar // round brackets. We did it to resolve the ambiguity when parsing scripts like: 1006bb7d2b17SGeorgii Rymar // SECTIONS { .foo : { ... } =120+3 /DISCARD/ : { ... } } 10070810f16fSGeorge Rimar std::array<uint8_t, 4> ScriptParser::readFill() { 1008bb7d2b17SGeorgii Rymar uint64_t value = readPrimary()().val; 10093837f427SRui Ueyama if (value > UINT32_MAX) 10100810f16fSGeorge Rimar setError("filler expression result does not fit 32-bit: 0x" + 10113837f427SRui Ueyama Twine::utohexstr(value)); 1012b58079d4SRui Ueyama 10133837f427SRui Ueyama std::array<uint8_t, 4> buf; 10143837f427SRui Ueyama write32be(buf.data(), (uint32_t)value); 10153837f427SRui Ueyama return buf; 10162ec34544SRui Ueyama } 10172ec34544SRui Ueyama 10183837f427SRui Ueyama SymbolAssignment *ScriptParser::readProvideHidden(bool provide, bool hidden) { 10192ec34544SRui Ueyama expect("("); 102021bf6bb3SFangrui Song StringRef name = next(), eq = peek(); 102121bf6bb3SFangrui Song if (eq != "=") { 102221bf6bb3SFangrui Song setError("= expected, but got " + next()); 102321bf6bb3SFangrui Song while (!atEOF() && next() != ")") 102421bf6bb3SFangrui Song ; 102521bf6bb3SFangrui Song return nullptr; 102621bf6bb3SFangrui Song } 102721bf6bb3SFangrui Song SymbolAssignment *cmd = readSymbolAssignment(name); 10283837f427SRui Ueyama cmd->provide = provide; 10293837f427SRui Ueyama cmd->hidden = hidden; 10302ec34544SRui Ueyama expect(")"); 10313837f427SRui Ueyama return cmd; 10322ec34544SRui Ueyama } 10332ec34544SRui Ueyama 10343837f427SRui Ueyama SymbolAssignment *ScriptParser::readAssignment(StringRef tok) { 1035d30a78b3SGeorge Rimar // Assert expression returns Dot, so this is equal to ".=." 10363837f427SRui Ueyama if (tok == "ASSERT") 1037d30a78b3SGeorge Rimar return make<SymbolAssignment>(".", readAssert(), getCurrentLocation()); 1038d30a78b3SGeorge Rimar 10393837f427SRui Ueyama size_t oldPos = pos; 10403837f427SRui Ueyama SymbolAssignment *cmd = nullptr; 1041*0a0effddSFangrui Song const StringRef op = peek(); 1042*0a0effddSFangrui Song if (op.startswith("=")) { 1043fe0de25bSFangrui Song // Support = followed by an expression without whitespace. 1044fe0de25bSFangrui Song SaveAndRestore<bool> saved(inExpr, true); 10453837f427SRui Ueyama cmd = readSymbolAssignment(tok); 1046*0a0effddSFangrui Song } else if ((op.size() == 2 && op[1] == '=' && 1047*0a0effddSFangrui Song is_contained("*/+-&|", op[0])) || 1048*0a0effddSFangrui Song op == "<<=" || op == ">>=") { 1049fe0de25bSFangrui Song cmd = readSymbolAssignment(tok); 1050fe0de25bSFangrui Song } else if (tok == "PROVIDE") { 1051fe0de25bSFangrui Song SaveAndRestore<bool> saved(inExpr, true); 10523837f427SRui Ueyama cmd = readProvideHidden(true, false); 1053fe0de25bSFangrui Song } else if (tok == "HIDDEN") { 1054fe0de25bSFangrui Song SaveAndRestore<bool> saved(inExpr, true); 10553837f427SRui Ueyama cmd = readProvideHidden(false, true); 1056fe0de25bSFangrui Song } else if (tok == "PROVIDE_HIDDEN") { 1057fe0de25bSFangrui Song SaveAndRestore<bool> saved(inExpr, true); 10583837f427SRui Ueyama cmd = readProvideHidden(true, true); 1059fe0de25bSFangrui Song } 1060e88b76a9SGeorge Rimar 10613837f427SRui Ueyama if (cmd) { 10623837f427SRui Ueyama cmd->commandString = 10633837f427SRui Ueyama tok.str() + " " + 10643837f427SRui Ueyama llvm::join(tokens.begin() + oldPos, tokens.begin() + pos, " "); 1065e88b76a9SGeorge Rimar expect(";"); 10662ec34544SRui Ueyama } 10673837f427SRui Ueyama return cmd; 10682ec34544SRui Ueyama } 10692ec34544SRui Ueyama 10703837f427SRui Ueyama SymbolAssignment *ScriptParser::readSymbolAssignment(StringRef name) { 1071e7a7ad13SFangrui Song name = unquote(name); 10723837f427SRui Ueyama StringRef op = next(); 1073*0a0effddSFangrui Song assert(op == "=" || op == "*=" || op == "/=" || op == "+=" || op == "-=" || 1074*0a0effddSFangrui Song op == "&=" || op == "|=" || op == "<<=" || op == ">>="); 1075*0a0effddSFangrui Song // Note: GNU ld does not support %= or ^=. 10763837f427SRui Ueyama Expr e = readExpr(); 1077*0a0effddSFangrui Song if (op != "=") { 10783837f427SRui Ueyama std::string loc = getCurrentLocation(); 1079*0a0effddSFangrui Song e = [=, c = op[0]]() -> ExprValue { 1080*0a0effddSFangrui Song ExprValue lhs = script->getSymbolValue(name, loc); 1081*0a0effddSFangrui Song switch (c) { 1082*0a0effddSFangrui Song case '*': 1083*0a0effddSFangrui Song return lhs.getValue() * e().getValue(); 1084*0a0effddSFangrui Song case '/': 1085*0a0effddSFangrui Song if (uint64_t rv = e().getValue()) 1086*0a0effddSFangrui Song return lhs.getValue() / rv; 1087*0a0effddSFangrui Song error(loc + ": division by zero"); 1088*0a0effddSFangrui Song return 0; 1089*0a0effddSFangrui Song case '+': 1090*0a0effddSFangrui Song return add(lhs, e()); 1091*0a0effddSFangrui Song case '-': 1092*0a0effddSFangrui Song return sub(lhs, e()); 1093*0a0effddSFangrui Song case '<': 1094*0a0effddSFangrui Song return lhs.getValue() << e().getValue(); 1095*0a0effddSFangrui Song case '>': 1096*0a0effddSFangrui Song return lhs.getValue() >> e().getValue(); 1097*0a0effddSFangrui Song case '&': 1098*0a0effddSFangrui Song return lhs.getValue() & e().getValue(); 1099*0a0effddSFangrui Song case '|': 1100*0a0effddSFangrui Song return lhs.getValue() | e().getValue(); 1101*0a0effddSFangrui Song default: 1102*0a0effddSFangrui Song llvm_unreachable(""); 1103*0a0effddSFangrui Song } 1104*0a0effddSFangrui Song }; 11052ec34544SRui Ueyama } 11063837f427SRui Ueyama return make<SymbolAssignment>(name, e, getCurrentLocation()); 11072ec34544SRui Ueyama } 11082ec34544SRui Ueyama 11092ec34544SRui Ueyama // This is an operator-precedence parser to parse a linker 11102ec34544SRui Ueyama // script expression. 11112ec34544SRui Ueyama Expr ScriptParser::readExpr() { 11122ec34544SRui Ueyama // Our lexer is context-aware. Set the in-expression bit so that 11132ec34544SRui Ueyama // they apply different tokenization rules. 11143837f427SRui Ueyama bool orig = inExpr; 11153837f427SRui Ueyama inExpr = true; 11163837f427SRui Ueyama Expr e = readExpr1(readPrimary(), 0); 11173837f427SRui Ueyama inExpr = orig; 11183837f427SRui Ueyama return e; 11192ec34544SRui Ueyama } 11202ec34544SRui Ueyama 11213837f427SRui Ueyama Expr ScriptParser::combine(StringRef op, Expr l, Expr r) { 11223837f427SRui Ueyama if (op == "+") 11233837f427SRui Ueyama return [=] { return add(l(), r()); }; 11243837f427SRui Ueyama if (op == "-") 11253837f427SRui Ueyama return [=] { return sub(l(), r()); }; 11263837f427SRui Ueyama if (op == "*") 11273837f427SRui Ueyama return [=] { return l().getValue() * r().getValue(); }; 11283837f427SRui Ueyama if (op == "/") { 11293837f427SRui Ueyama std::string loc = getCurrentLocation(); 11307b91e213SGeorge Rimar return [=]() -> uint64_t { 11313837f427SRui Ueyama if (uint64_t rv = r().getValue()) 11323837f427SRui Ueyama return l().getValue() / rv; 11333837f427SRui Ueyama error(loc + ": division by zero"); 1134067617f9SRui Ueyama return 0; 11357b91e213SGeorge Rimar }; 11367b91e213SGeorge Rimar } 11373837f427SRui Ueyama if (op == "%") { 11383837f427SRui Ueyama std::string loc = getCurrentLocation(); 11397b91e213SGeorge Rimar return [=]() -> uint64_t { 11403837f427SRui Ueyama if (uint64_t rv = r().getValue()) 11413837f427SRui Ueyama return l().getValue() % rv; 11423837f427SRui Ueyama error(loc + ": modulo by zero"); 1143067617f9SRui Ueyama return 0; 11447b91e213SGeorge Rimar }; 11457b91e213SGeorge Rimar } 11463837f427SRui Ueyama if (op == "<<") 11473837f427SRui Ueyama return [=] { return l().getValue() << r().getValue(); }; 11483837f427SRui Ueyama if (op == ">>") 11493837f427SRui Ueyama return [=] { return l().getValue() >> r().getValue(); }; 11503837f427SRui Ueyama if (op == "<") 11513837f427SRui Ueyama return [=] { return l().getValue() < r().getValue(); }; 11523837f427SRui Ueyama if (op == ">") 11533837f427SRui Ueyama return [=] { return l().getValue() > r().getValue(); }; 11543837f427SRui Ueyama if (op == ">=") 11553837f427SRui Ueyama return [=] { return l().getValue() >= r().getValue(); }; 11563837f427SRui Ueyama if (op == "<=") 11573837f427SRui Ueyama return [=] { return l().getValue() <= r().getValue(); }; 11583837f427SRui Ueyama if (op == "==") 11593837f427SRui Ueyama return [=] { return l().getValue() == r().getValue(); }; 11603837f427SRui Ueyama if (op == "!=") 11613837f427SRui Ueyama return [=] { return l().getValue() != r().getValue(); }; 11623837f427SRui Ueyama if (op == "||") 11633837f427SRui Ueyama return [=] { return l().getValue() || r().getValue(); }; 11643837f427SRui Ueyama if (op == "&&") 11653837f427SRui Ueyama return [=] { return l().getValue() && r().getValue(); }; 11663837f427SRui Ueyama if (op == "&") 11673837f427SRui Ueyama return [=] { return bitAnd(l(), r()); }; 11683837f427SRui Ueyama if (op == "|") 11693837f427SRui Ueyama return [=] { return bitOr(l(), r()); }; 11702ec34544SRui Ueyama llvm_unreachable("invalid operator"); 11712ec34544SRui Ueyama } 11722ec34544SRui Ueyama 11732ec34544SRui Ueyama // This is a part of the operator-precedence parser. This function 11742ec34544SRui Ueyama // assumes that the remaining token stream starts with an operator. 11753837f427SRui Ueyama Expr ScriptParser::readExpr1(Expr lhs, int minPrec) { 1176b8a59c8aSBob Haarman while (!atEOF() && !errorCount()) { 11772ec34544SRui Ueyama // Read an operator and an expression. 11783837f427SRui Ueyama StringRef op1 = peek(); 11793837f427SRui Ueyama if (precedence(op1) < minPrec) 11802ec34544SRui Ueyama break; 1181b0d6dd39SFangrui Song if (consume("?")) 1182b0d6dd39SFangrui Song return readTernary(lhs); 11832ec34544SRui Ueyama skip(); 11843837f427SRui Ueyama Expr rhs = readPrimary(); 11852ec34544SRui Ueyama 11862ec34544SRui Ueyama // Evaluate the remaining part of the expression first if the 11872ec34544SRui Ueyama // next operator has greater precedence than the previous one. 11882ec34544SRui Ueyama // For example, if we have read "+" and "3", and if the next 11892ec34544SRui Ueyama // operator is "*", then we'll evaluate 3 * ... part first. 11902ec34544SRui Ueyama while (!atEOF()) { 11913837f427SRui Ueyama StringRef op2 = peek(); 11923837f427SRui Ueyama if (precedence(op2) <= precedence(op1)) 11932ec34544SRui Ueyama break; 11943837f427SRui Ueyama rhs = readExpr1(rhs, precedence(op2)); 11952ec34544SRui Ueyama } 11962ec34544SRui Ueyama 11973837f427SRui Ueyama lhs = combine(op1, lhs, rhs); 11982ec34544SRui Ueyama } 11993837f427SRui Ueyama return lhs; 12002ec34544SRui Ueyama } 12012ec34544SRui Ueyama 12025fb17128SGeorge Rimar Expr ScriptParser::getPageSize() { 12033837f427SRui Ueyama std::string location = getCurrentLocation(); 12045fb17128SGeorge Rimar return [=]() -> uint64_t { 12053837f427SRui Ueyama if (target) 12063837f427SRui Ueyama return config->commonPageSize; 12073837f427SRui Ueyama error(location + ": unable to calculate page size"); 12085fb17128SGeorge Rimar return 4096; // Return a dummy value. 12095fb17128SGeorge Rimar }; 12105fb17128SGeorge Rimar } 12115fb17128SGeorge Rimar 12125fb17128SGeorge Rimar Expr ScriptParser::readConstant() { 12133837f427SRui Ueyama StringRef s = readParenLiteral(); 12143837f427SRui Ueyama if (s == "COMMONPAGESIZE") 12155fb17128SGeorge Rimar return getPageSize(); 12163837f427SRui Ueyama if (s == "MAXPAGESIZE") 12173837f427SRui Ueyama return [] { return config->maxPageSize; }; 12183837f427SRui Ueyama setError("unknown constant: " + s); 1219b068b037SGeorge Rimar return [] { return 0; }; 12202ec34544SRui Ueyama } 12212ec34544SRui Ueyama 12225c65088fSRui Ueyama // Parses Tok as an integer. It recognizes hexadecimal (prefixed with 12235c65088fSRui Ueyama // "0x" or suffixed with "H") and decimal numbers. Decimal numbers may 12245c65088fSRui Ueyama // have "K" (Ki) or "M" (Mi) suffixes. 12253837f427SRui Ueyama static Optional<uint64_t> parseInt(StringRef tok) { 12262ec34544SRui Ueyama // Hexadecimal 12273837f427SRui Ueyama uint64_t val; 12283c6f8ca7SMartin Storsjö if (tok.startswith_insensitive("0x")) { 12293837f427SRui Ueyama if (!to_integer(tok.substr(2), val, 16)) 12304092016bSRui Ueyama return None; 12313837f427SRui Ueyama return val; 12324092016bSRui Ueyama } 12333c6f8ca7SMartin Storsjö if (tok.endswith_insensitive("H")) { 12343837f427SRui Ueyama if (!to_integer(tok.drop_back(), val, 16)) 12354092016bSRui Ueyama return None; 12363837f427SRui Ueyama return val; 12374092016bSRui Ueyama } 12382ec34544SRui Ueyama 12392ec34544SRui Ueyama // Decimal 12403c6f8ca7SMartin Storsjö if (tok.endswith_insensitive("K")) { 12413837f427SRui Ueyama if (!to_integer(tok.drop_back(), val, 10)) 12425c65088fSRui Ueyama return None; 12433837f427SRui Ueyama return val * 1024; 12442ec34544SRui Ueyama } 12453c6f8ca7SMartin Storsjö if (tok.endswith_insensitive("M")) { 12463837f427SRui Ueyama if (!to_integer(tok.drop_back(), val, 10)) 12475c65088fSRui Ueyama return None; 12483837f427SRui Ueyama return val * 1024 * 1024; 12495c65088fSRui Ueyama } 12503837f427SRui Ueyama if (!to_integer(tok, val, 10)) 12515c65088fSRui Ueyama return None; 12523837f427SRui Ueyama return val; 12532ec34544SRui Ueyama } 12542ec34544SRui Ueyama 12553837f427SRui Ueyama ByteCommand *ScriptParser::readByteCommand(StringRef tok) { 12563837f427SRui Ueyama int size = StringSwitch<int>(tok) 12572ec34544SRui Ueyama .Case("BYTE", 1) 12582ec34544SRui Ueyama .Case("SHORT", 2) 12592ec34544SRui Ueyama .Case("LONG", 4) 12602ec34544SRui Ueyama .Case("QUAD", 8) 12612ec34544SRui Ueyama .Default(-1); 12623837f427SRui Ueyama if (size == -1) 12632ec34544SRui Ueyama return nullptr; 126484bcabcbSGeorge Rimar 12653837f427SRui Ueyama size_t oldPos = pos; 12663837f427SRui Ueyama Expr e = readParenExpr(); 12673837f427SRui Ueyama std::string commandString = 12683837f427SRui Ueyama tok.str() + " " + 12693837f427SRui Ueyama llvm::join(tokens.begin() + oldPos, tokens.begin() + pos, " "); 12703837f427SRui Ueyama return make<ByteCommand>(e, size, commandString); 12712ec34544SRui Ueyama } 12722ec34544SRui Ueyama 1273dbd0ad33SPeter Smith static llvm::Optional<uint64_t> parseFlag(StringRef tok) { 1274dbd0ad33SPeter Smith if (llvm::Optional<uint64_t> asInt = parseInt(tok)) 1275dbd0ad33SPeter Smith return asInt; 1276dbd0ad33SPeter Smith #define CASE_ENT(enum) #enum, ELF::enum 1277dbd0ad33SPeter Smith return StringSwitch<llvm::Optional<uint64_t>>(tok) 1278dbd0ad33SPeter Smith .Case(CASE_ENT(SHF_WRITE)) 1279dbd0ad33SPeter Smith .Case(CASE_ENT(SHF_ALLOC)) 1280dbd0ad33SPeter Smith .Case(CASE_ENT(SHF_EXECINSTR)) 1281dbd0ad33SPeter Smith .Case(CASE_ENT(SHF_MERGE)) 1282dbd0ad33SPeter Smith .Case(CASE_ENT(SHF_STRINGS)) 1283dbd0ad33SPeter Smith .Case(CASE_ENT(SHF_INFO_LINK)) 1284dbd0ad33SPeter Smith .Case(CASE_ENT(SHF_LINK_ORDER)) 1285dbd0ad33SPeter Smith .Case(CASE_ENT(SHF_OS_NONCONFORMING)) 1286dbd0ad33SPeter Smith .Case(CASE_ENT(SHF_GROUP)) 1287dbd0ad33SPeter Smith .Case(CASE_ENT(SHF_TLS)) 1288dbd0ad33SPeter Smith .Case(CASE_ENT(SHF_COMPRESSED)) 1289dbd0ad33SPeter Smith .Case(CASE_ENT(SHF_EXCLUDE)) 1290dbd0ad33SPeter Smith .Case(CASE_ENT(SHF_ARM_PURECODE)) 1291dbd0ad33SPeter Smith .Default(None); 1292dbd0ad33SPeter Smith #undef CASE_ENT 1293dbd0ad33SPeter Smith } 1294dbd0ad33SPeter Smith 1295dbd0ad33SPeter Smith // Reads the '(' <flags> ')' list of section flags in 1296dbd0ad33SPeter Smith // INPUT_SECTION_FLAGS '(' <flags> ')' in the 1297dbd0ad33SPeter Smith // following form: 1298dbd0ad33SPeter Smith // <flags> ::= <flag> 1299dbd0ad33SPeter Smith // | <flags> & flag 1300dbd0ad33SPeter Smith // <flag> ::= Recognized Flag Name, or Integer value of flag. 1301dbd0ad33SPeter Smith // If the first character of <flag> is a ! then this means without flag, 1302dbd0ad33SPeter Smith // otherwise with flag. 1303dbd0ad33SPeter Smith // Example: SHF_EXECINSTR & !SHF_WRITE means with flag SHF_EXECINSTR and 1304dbd0ad33SPeter Smith // without flag SHF_WRITE. 1305dbd0ad33SPeter Smith std::pair<uint64_t, uint64_t> ScriptParser::readInputSectionFlags() { 1306dbd0ad33SPeter Smith uint64_t withFlags = 0; 1307dbd0ad33SPeter Smith uint64_t withoutFlags = 0; 1308dbd0ad33SPeter Smith expect("("); 1309dbd0ad33SPeter Smith while (!errorCount()) { 1310dbd0ad33SPeter Smith StringRef tok = unquote(next()); 1311dbd0ad33SPeter Smith bool without = tok.consume_front("!"); 1312dbd0ad33SPeter Smith if (llvm::Optional<uint64_t> flag = parseFlag(tok)) { 1313dbd0ad33SPeter Smith if (without) 1314dbd0ad33SPeter Smith withoutFlags |= *flag; 1315dbd0ad33SPeter Smith else 1316dbd0ad33SPeter Smith withFlags |= *flag; 1317dbd0ad33SPeter Smith } else { 1318dbd0ad33SPeter Smith setError("unrecognised flag: " + tok); 1319dbd0ad33SPeter Smith } 1320dbd0ad33SPeter Smith if (consume(")")) 1321dbd0ad33SPeter Smith break; 1322dbd0ad33SPeter Smith if (!consume("&")) { 1323dbd0ad33SPeter Smith next(); 1324dbd0ad33SPeter Smith setError("expected & or )"); 1325dbd0ad33SPeter Smith } 1326dbd0ad33SPeter Smith } 1327dbd0ad33SPeter Smith return std::make_pair(withFlags, withoutFlags); 1328dbd0ad33SPeter Smith } 1329dbd0ad33SPeter Smith 13302ec34544SRui Ueyama StringRef ScriptParser::readParenLiteral() { 13312ec34544SRui Ueyama expect("("); 13323837f427SRui Ueyama bool orig = inExpr; 13333837f427SRui Ueyama inExpr = false; 13343837f427SRui Ueyama StringRef tok = next(); 13353837f427SRui Ueyama inExpr = orig; 13362ec34544SRui Ueyama expect(")"); 13373837f427SRui Ueyama return tok; 13382ec34544SRui Ueyama } 13392ec34544SRui Ueyama 13409e9c86fdSFangrui Song static void checkIfExists(const OutputSection &osec, StringRef location) { 13419e9c86fdSFangrui Song if (osec.location.empty() && script->errorOnMissingSection) 13429e9c86fdSFangrui Song error(location + ": undefined section " + osec.name); 134305c4f67cSRafael Espindola } 134405c4f67cSRafael Espindola 1345e4f385d8SFangrui Song static bool isValidSymbolName(StringRef s) { 1346e4f385d8SFangrui Song auto valid = [](char c) { 1347e4f385d8SFangrui Song return isAlnum(c) || c == '$' || c == '.' || c == '_'; 1348e4f385d8SFangrui Song }; 1349e4f385d8SFangrui Song return !s.empty() && !isDigit(s[0]) && llvm::all_of(s, valid); 1350e4f385d8SFangrui Song } 1351e4f385d8SFangrui Song 13522ec34544SRui Ueyama Expr ScriptParser::readPrimary() { 13532ec34544SRui Ueyama if (peek() == "(") 13542ec34544SRui Ueyama return readParenExpr(); 13552ec34544SRui Ueyama 13565c65088fSRui Ueyama if (consume("~")) { 13573837f427SRui Ueyama Expr e = readPrimary(); 13583837f427SRui Ueyama return [=] { return ~e().getValue(); }; 13592ec34544SRui Ueyama } 13606f1d954eSHafiz Abid Qadeer if (consume("!")) { 13613837f427SRui Ueyama Expr e = readPrimary(); 13623837f427SRui Ueyama return [=] { return !e().getValue(); }; 13636f1d954eSHafiz Abid Qadeer } 13645c65088fSRui Ueyama if (consume("-")) { 13653837f427SRui Ueyama Expr e = readPrimary(); 13663837f427SRui Ueyama return [=] { return -e().getValue(); }; 13672ec34544SRui Ueyama } 13682ec34544SRui Ueyama 13693837f427SRui Ueyama StringRef tok = next(); 13703837f427SRui Ueyama std::string location = getCurrentLocation(); 13715c65088fSRui Ueyama 13722ec34544SRui Ueyama // Built-in functions are parsed here. 13732ec34544SRui Ueyama // https://sourceware.org/binutils/docs/ld/Builtin-Functions.html. 13743837f427SRui Ueyama if (tok == "ABSOLUTE") { 13753837f427SRui Ueyama Expr inner = readParenExpr(); 13762ec34544SRui Ueyama return [=] { 13773837f427SRui Ueyama ExprValue i = inner(); 13783837f427SRui Ueyama i.forceAbsolute = true; 13793837f427SRui Ueyama return i; 13802ec34544SRui Ueyama }; 13812ec34544SRui Ueyama } 13823837f427SRui Ueyama if (tok == "ADDR") { 13833837f427SRui Ueyama StringRef name = readParenLiteral(); 13846c814931SFangrui Song OutputSection *osec = &script->getOrCreateOutputSection(name)->osec; 13859e9c86fdSFangrui Song osec->usedInExpression = true; 138641c7ab4aSGeorge Rimar return [=]() -> ExprValue { 13879e9c86fdSFangrui Song checkIfExists(*osec, location); 13889e9c86fdSFangrui Song return {osec, false, 0, location}; 138941c7ab4aSGeorge Rimar }; 13902ec34544SRui Ueyama } 13913837f427SRui Ueyama if (tok == "ALIGN") { 13922ec34544SRui Ueyama expect("("); 13933837f427SRui Ueyama Expr e = readExpr(); 1394f22ec9ddSGeorge Rimar if (consume(")")) { 13953837f427SRui Ueyama e = checkAlignment(e, location); 13963837f427SRui Ueyama return [=] { return alignTo(script->getDot(), e().getValue()); }; 1397f22ec9ddSGeorge Rimar } 1398b579c439SRui Ueyama expect(","); 13993837f427SRui Ueyama Expr e2 = checkAlignment(readExpr(), location); 14002ec34544SRui Ueyama expect(")"); 14013c6de1a6SPetr Hosek return [=] { 14023837f427SRui Ueyama ExprValue v = e(); 14033837f427SRui Ueyama v.alignment = e2().getValue(); 14043837f427SRui Ueyama return v; 14053c6de1a6SPetr Hosek }; 14062ec34544SRui Ueyama } 14073837f427SRui Ueyama if (tok == "ALIGNOF") { 14083837f427SRui Ueyama StringRef name = readParenLiteral(); 14096c814931SFangrui Song OutputSection *osec = &script->getOrCreateOutputSection(name)->osec; 1410617e2f98SRui Ueyama return [=] { 14119e9c86fdSFangrui Song checkIfExists(*osec, location); 14129e9c86fdSFangrui Song return osec->alignment; 1413617e2f98SRui Ueyama }; 14142ec34544SRui Ueyama } 14153837f427SRui Ueyama if (tok == "ASSERT") 1416d30a78b3SGeorge Rimar return readAssert(); 14173837f427SRui Ueyama if (tok == "CONSTANT") 14185fb17128SGeorge Rimar return readConstant(); 14193837f427SRui Ueyama if (tok == "DATA_SEGMENT_ALIGN") { 14202ec34544SRui Ueyama expect("("); 14213837f427SRui Ueyama Expr e = readExpr(); 14222ec34544SRui Ueyama expect(","); 14232ec34544SRui Ueyama readExpr(); 14242ec34544SRui Ueyama expect(")"); 14255a44980fSFangrui Song seenDataAlign = true; 142660833f6eSGeorge Rimar return [=] { 14273837f427SRui Ueyama return alignTo(script->getDot(), std::max((uint64_t)1, e().getValue())); 142860833f6eSGeorge Rimar }; 14292ec34544SRui Ueyama } 14303837f427SRui Ueyama if (tok == "DATA_SEGMENT_END") { 14312ec34544SRui Ueyama expect("("); 14322ec34544SRui Ueyama expect("."); 14332ec34544SRui Ueyama expect(")"); 14343837f427SRui Ueyama return [] { return script->getDot(); }; 14352ec34544SRui Ueyama } 14363837f427SRui Ueyama if (tok == "DATA_SEGMENT_RELRO_END") { 14372ec34544SRui Ueyama // GNU linkers implements more complicated logic to handle 14382ec34544SRui Ueyama // DATA_SEGMENT_RELRO_END. We instead ignore the arguments and 14392ec34544SRui Ueyama // just align to the next page boundary for simplicity. 14402ec34544SRui Ueyama expect("("); 14412ec34544SRui Ueyama readExpr(); 14422ec34544SRui Ueyama expect(","); 14432ec34544SRui Ueyama readExpr(); 14442ec34544SRui Ueyama expect(")"); 14455a44980fSFangrui Song seenRelroEnd = true; 14463837f427SRui Ueyama Expr e = getPageSize(); 14473837f427SRui Ueyama return [=] { return alignTo(script->getDot(), e().getValue()); }; 14482ec34544SRui Ueyama } 14493837f427SRui Ueyama if (tok == "DEFINED") { 1450e7a7ad13SFangrui Song StringRef name = unquote(readParenLiteral()); 14511f166edeSHafiz Abid Qadeer return [=] { 14521f166edeSHafiz Abid Qadeer Symbol *b = symtab->find(name); 14531f166edeSHafiz Abid Qadeer return (b && b->isDefined()) ? 1 : 0; 14541f166edeSHafiz Abid Qadeer }; 14552ec34544SRui Ueyama } 14563837f427SRui Ueyama if (tok == "LENGTH") { 14573837f427SRui Ueyama StringRef name = readParenLiteral(); 14583837f427SRui Ueyama if (script->memoryRegions.count(name) == 0) { 14593837f427SRui Ueyama setError("memory region not defined: " + name); 1460b068b037SGeorge Rimar return [] { return 0; }; 1461b068b037SGeorge Rimar } 146292b5b980SFangrui Song return script->memoryRegions[name]->length; 146391b95b61SRui Ueyama } 14643837f427SRui Ueyama if (tok == "LOADADDR") { 14653837f427SRui Ueyama StringRef name = readParenLiteral(); 14666c814931SFangrui Song OutputSection *osec = &script->getOrCreateOutputSection(name)->osec; 14679e9c86fdSFangrui Song osec->usedInExpression = true; 1468617e2f98SRui Ueyama return [=] { 14699e9c86fdSFangrui Song checkIfExists(*osec, location); 14709e9c86fdSFangrui Song return osec->getLMA(); 1471617e2f98SRui Ueyama }; 14722ec34544SRui Ueyama } 1473fa1145a8SIsaac Richter if (tok == "LOG2CEIL") { 1474fa1145a8SIsaac Richter expect("("); 1475fa1145a8SIsaac Richter Expr a = readExpr(); 1476fa1145a8SIsaac Richter expect(")"); 1477fa1145a8SIsaac Richter return [=] { 1478fa1145a8SIsaac Richter // LOG2CEIL(0) is defined to be 0. 1479fa1145a8SIsaac Richter return llvm::Log2_64_Ceil(std::max(a().getValue(), UINT64_C(1))); 1480fa1145a8SIsaac Richter }; 1481fa1145a8SIsaac Richter } 14823837f427SRui Ueyama if (tok == "MAX" || tok == "MIN") { 1483fd11560fSGeorge Rimar expect("("); 14843837f427SRui Ueyama Expr a = readExpr(); 1485fd11560fSGeorge Rimar expect(","); 14863837f427SRui Ueyama Expr b = readExpr(); 1487fd11560fSGeorge Rimar expect(")"); 14883837f427SRui Ueyama if (tok == "MIN") 14893837f427SRui Ueyama return [=] { return std::min(a().getValue(), b().getValue()); }; 14903837f427SRui Ueyama return [=] { return std::max(a().getValue(), b().getValue()); }; 1491fd11560fSGeorge Rimar } 14923837f427SRui Ueyama if (tok == "ORIGIN") { 14933837f427SRui Ueyama StringRef name = readParenLiteral(); 14943837f427SRui Ueyama if (script->memoryRegions.count(name) == 0) { 14953837f427SRui Ueyama setError("memory region not defined: " + name); 1496b068b037SGeorge Rimar return [] { return 0; }; 1497b068b037SGeorge Rimar } 149892b5b980SFangrui Song return script->memoryRegions[name]->origin; 149991b95b61SRui Ueyama } 15003837f427SRui Ueyama if (tok == "SEGMENT_START") { 15012ec34544SRui Ueyama expect("("); 15022ec34544SRui Ueyama skip(); 15032ec34544SRui Ueyama expect(","); 15043837f427SRui Ueyama Expr e = readExpr(); 15052ec34544SRui Ueyama expect(")"); 15063837f427SRui Ueyama return [=] { return e(); }; 15072ec34544SRui Ueyama } 15083837f427SRui Ueyama if (tok == "SIZEOF") { 15093837f427SRui Ueyama StringRef name = readParenLiteral(); 15106c814931SFangrui Song OutputSection *cmd = &script->getOrCreateOutputSection(name)->osec; 151105c4f67cSRafael Espindola // Linker script does not create an output section if its content is empty. 151205c4f67cSRafael Espindola // We want to allow SIZEOF(.foo) where .foo is a section which happened to 151305c4f67cSRafael Espindola // be empty. 15143837f427SRui Ueyama return [=] { return cmd->size; }; 15152ec34544SRui Ueyama } 15163837f427SRui Ueyama if (tok == "SIZEOF_HEADERS") 151707837b8fSFangrui Song return [=] { return elf::getHeaderSize(); }; 15182ec34544SRui Ueyama 15194eb2eccbSRui Ueyama // Tok is the dot. 15203837f427SRui Ueyama if (tok == ".") 15213837f427SRui Ueyama return [=] { return script->getSymbolValue(tok, location); }; 15224eb2eccbSRui Ueyama 15232ec34544SRui Ueyama // Tok is a literal number. 15243837f427SRui Ueyama if (Optional<uint64_t> val = parseInt(tok)) 15253837f427SRui Ueyama return [=] { return *val; }; 15262ec34544SRui Ueyama 15272ec34544SRui Ueyama // Tok is a symbol name. 15282bf06d93SFangrui Song if (tok.startswith("\"")) 1529e7a7ad13SFangrui Song tok = unquote(tok); 15302bf06d93SFangrui Song else if (!isValidSymbolName(tok)) 15313837f427SRui Ueyama setError("malformed number: " + tok); 15323837f427SRui Ueyama script->referencedSymbols.push_back(tok); 15333837f427SRui Ueyama return [=] { return script->getSymbolValue(tok, location); }; 15342ec34544SRui Ueyama } 15352ec34544SRui Ueyama 15363837f427SRui Ueyama Expr ScriptParser::readTernary(Expr cond) { 15373837f427SRui Ueyama Expr l = readExpr(); 15382ec34544SRui Ueyama expect(":"); 15393837f427SRui Ueyama Expr r = readExpr(); 15403837f427SRui Ueyama return [=] { return cond().getValue() ? l() : r(); }; 15412ec34544SRui Ueyama } 15422ec34544SRui Ueyama 15432ec34544SRui Ueyama Expr ScriptParser::readParenExpr() { 15442ec34544SRui Ueyama expect("("); 15453837f427SRui Ueyama Expr e = readExpr(); 15462ec34544SRui Ueyama expect(")"); 15473837f427SRui Ueyama return e; 15482ec34544SRui Ueyama } 15492ec34544SRui Ueyama 1550a1c2ee01SFangrui Song SmallVector<StringRef, 0> ScriptParser::readOutputSectionPhdrs() { 1551a1c2ee01SFangrui Song SmallVector<StringRef, 0> phdrs; 1552b8a59c8aSBob Haarman while (!errorCount() && peek().startswith(":")) { 15533837f427SRui Ueyama StringRef tok = next(); 15543837f427SRui Ueyama phdrs.push_back((tok.size() == 1) ? next() : tok.substr(1)); 15552ec34544SRui Ueyama } 15563837f427SRui Ueyama return phdrs; 15572ec34544SRui Ueyama } 15582ec34544SRui Ueyama 15592ec34544SRui Ueyama // Read a program header type name. The next token must be a 15602ec34544SRui Ueyama // name of a program header type or a constant (e.g. "0x3"). 15612ec34544SRui Ueyama unsigned ScriptParser::readPhdrType() { 15623837f427SRui Ueyama StringRef tok = next(); 15633837f427SRui Ueyama if (Optional<uint64_t> val = parseInt(tok)) 15643837f427SRui Ueyama return *val; 15652ec34544SRui Ueyama 15663837f427SRui Ueyama unsigned ret = StringSwitch<unsigned>(tok) 15672ec34544SRui Ueyama .Case("PT_NULL", PT_NULL) 15682ec34544SRui Ueyama .Case("PT_LOAD", PT_LOAD) 15692ec34544SRui Ueyama .Case("PT_DYNAMIC", PT_DYNAMIC) 15702ec34544SRui Ueyama .Case("PT_INTERP", PT_INTERP) 15712ec34544SRui Ueyama .Case("PT_NOTE", PT_NOTE) 15722ec34544SRui Ueyama .Case("PT_SHLIB", PT_SHLIB) 15732ec34544SRui Ueyama .Case("PT_PHDR", PT_PHDR) 15742ec34544SRui Ueyama .Case("PT_TLS", PT_TLS) 15752ec34544SRui Ueyama .Case("PT_GNU_EH_FRAME", PT_GNU_EH_FRAME) 15762ec34544SRui Ueyama .Case("PT_GNU_STACK", PT_GNU_STACK) 15772ec34544SRui Ueyama .Case("PT_GNU_RELRO", PT_GNU_RELRO) 15782ec34544SRui Ueyama .Case("PT_OPENBSD_RANDOMIZE", PT_OPENBSD_RANDOMIZE) 15792ec34544SRui Ueyama .Case("PT_OPENBSD_WXNEEDED", PT_OPENBSD_WXNEEDED) 15802ec34544SRui Ueyama .Case("PT_OPENBSD_BOOTDATA", PT_OPENBSD_BOOTDATA) 15812ec34544SRui Ueyama .Default(-1); 15822ec34544SRui Ueyama 15833837f427SRui Ueyama if (ret == (unsigned)-1) { 15843837f427SRui Ueyama setError("invalid program header type: " + tok); 15852ec34544SRui Ueyama return PT_NULL; 15862ec34544SRui Ueyama } 15873837f427SRui Ueyama return ret; 15882ec34544SRui Ueyama } 15892ec34544SRui Ueyama 15902ec34544SRui Ueyama // Reads an anonymous version declaration. 15912ec34544SRui Ueyama void ScriptParser::readAnonymousDeclaration() { 159264038ef8SFangrui Song SmallVector<SymbolVersion, 0> locals; 159364038ef8SFangrui Song SmallVector<SymbolVersion, 0> globals; 15943837f427SRui Ueyama std::tie(locals, globals) = readSymbols(); 1595e28a70daSFangrui Song for (const SymbolVersion &pat : locals) 159600809c88SFangrui Song config->versionDefinitions[VER_NDX_LOCAL].localPatterns.push_back(pat); 1597e28a70daSFangrui Song for (const SymbolVersion &pat : globals) 159800809c88SFangrui Song config->versionDefinitions[VER_NDX_GLOBAL].nonLocalPatterns.push_back(pat); 15992ec34544SRui Ueyama 16002ec34544SRui Ueyama expect(";"); 16012ec34544SRui Ueyama } 16022ec34544SRui Ueyama 16032ec34544SRui Ueyama // Reads a non-anonymous version definition, 16042ec34544SRui Ueyama // e.g. "VerStr { global: foo; bar; local: *; };". 16053837f427SRui Ueyama void ScriptParser::readVersionDeclaration(StringRef verStr) { 16062ec34544SRui Ueyama // Read a symbol list. 160764038ef8SFangrui Song SmallVector<SymbolVersion, 0> locals; 160864038ef8SFangrui Song SmallVector<SymbolVersion, 0> globals; 16093837f427SRui Ueyama std::tie(locals, globals) = readSymbols(); 16102ec34544SRui Ueyama 16112ec34544SRui Ueyama // Create a new version definition and add that to the global symbols. 16123837f427SRui Ueyama VersionDefinition ver; 16133837f427SRui Ueyama ver.name = verStr; 161400809c88SFangrui Song ver.nonLocalPatterns = std::move(globals); 161500809c88SFangrui Song ver.localPatterns = std::move(locals); 1616e28a70daSFangrui Song ver.id = config->versionDefinitions.size(); 16173837f427SRui Ueyama config->versionDefinitions.push_back(ver); 16182ec34544SRui Ueyama 16192ec34544SRui Ueyama // Each version may have a parent version. For example, "Ver2" 16202ec34544SRui Ueyama // defined as "Ver2 { global: foo; local: *; } Ver1;" has "Ver1" 16212ec34544SRui Ueyama // as a parent. This version hierarchy is, probably against your 16222ec34544SRui Ueyama // instinct, purely for hint; the runtime doesn't care about it 16232ec34544SRui Ueyama // at all. In LLD, we simply ignore it. 16245f380403SFangrui Song if (next() != ";") 16252ec34544SRui Ueyama expect(";"); 16262ec34544SRui Ueyama } 16272ec34544SRui Ueyama 162849279ca1SFangrui Song bool elf::hasWildcard(StringRef s) { 16293837f427SRui Ueyama return s.find_first_of("?*[") != StringRef::npos; 16301e77ad14SRui Ueyama } 16311e77ad14SRui Ueyama 16322ec34544SRui Ueyama // Reads a list of symbols, e.g. "{ global: foo; bar; local: *; };". 163364038ef8SFangrui Song std::pair<SmallVector<SymbolVersion, 0>, SmallVector<SymbolVersion, 0>> 16342ec34544SRui Ueyama ScriptParser::readSymbols() { 163564038ef8SFangrui Song SmallVector<SymbolVersion, 0> locals; 163664038ef8SFangrui Song SmallVector<SymbolVersion, 0> globals; 163764038ef8SFangrui Song SmallVector<SymbolVersion, 0> *v = &globals; 16382ec34544SRui Ueyama 1639b8a59c8aSBob Haarman while (!errorCount()) { 16402ec34544SRui Ueyama if (consume("}")) 16412ec34544SRui Ueyama break; 16422ec34544SRui Ueyama if (consumeLabel("local")) { 16433837f427SRui Ueyama v = &locals; 16442ec34544SRui Ueyama continue; 16452ec34544SRui Ueyama } 16462ec34544SRui Ueyama if (consumeLabel("global")) { 16473837f427SRui Ueyama v = &globals; 16482ec34544SRui Ueyama continue; 16492ec34544SRui Ueyama } 16502ec34544SRui Ueyama 16512ec34544SRui Ueyama if (consume("extern")) { 165264038ef8SFangrui Song SmallVector<SymbolVersion, 0> ext = readVersionExtern(); 16533837f427SRui Ueyama v->insert(v->end(), ext.begin(), ext.end()); 16542ec34544SRui Ueyama } else { 16553837f427SRui Ueyama StringRef tok = next(); 16563837f427SRui Ueyama v->push_back({unquote(tok), false, hasWildcard(tok)}); 16572ec34544SRui Ueyama } 16582ec34544SRui Ueyama expect(";"); 16592ec34544SRui Ueyama } 16603837f427SRui Ueyama return {locals, globals}; 16612ec34544SRui Ueyama } 16622ec34544SRui Ueyama 16632ec34544SRui Ueyama // Reads an "extern C++" directive, e.g., 16642ec34544SRui Ueyama // "extern "C++" { ns::*; "f(int, double)"; };" 166517324d8bSRui Ueyama // 166617324d8bSRui Ueyama // The last semicolon is optional. E.g. this is OK: 166717324d8bSRui Ueyama // "extern "C++" { ns::*; "f(int, double)" };" 166864038ef8SFangrui Song SmallVector<SymbolVersion, 0> ScriptParser::readVersionExtern() { 16693837f427SRui Ueyama StringRef tok = next(); 16703837f427SRui Ueyama bool isCXX = tok == "\"C++\""; 16713837f427SRui Ueyama if (!isCXX && tok != "\"C\"") 16722ec34544SRui Ueyama setError("Unknown language"); 16732ec34544SRui Ueyama expect("{"); 16742ec34544SRui Ueyama 167564038ef8SFangrui Song SmallVector<SymbolVersion, 0> ret; 1676b8a59c8aSBob Haarman while (!errorCount() && peek() != "}") { 16773837f427SRui Ueyama StringRef tok = next(); 16783837f427SRui Ueyama ret.push_back( 16793837f427SRui Ueyama {unquote(tok), isCXX, !tok.startswith("\"") && hasWildcard(tok)}); 168017324d8bSRui Ueyama if (consume("}")) 16813837f427SRui Ueyama return ret; 16822ec34544SRui Ueyama expect(";"); 16832ec34544SRui Ueyama } 16842ec34544SRui Ueyama 16852ec34544SRui Ueyama expect("}"); 16863837f427SRui Ueyama return ret; 16872ec34544SRui Ueyama } 16882ec34544SRui Ueyama 168992b5b980SFangrui Song Expr ScriptParser::readMemoryAssignment(StringRef s1, StringRef s2, 16903837f427SRui Ueyama StringRef s3) { 16913837f427SRui Ueyama if (!consume(s1) && !consume(s2) && !consume(s3)) { 16923837f427SRui Ueyama setError("expected one of: " + s1 + ", " + s2 + ", or " + s3); 169392b5b980SFangrui Song return [] { return 0; }; 16942ec34544SRui Ueyama } 16952ec34544SRui Ueyama expect("="); 169692b5b980SFangrui Song return readExpr(); 16972ec34544SRui Ueyama } 16982ec34544SRui Ueyama 16992ec34544SRui Ueyama // Parse the MEMORY command as specified in: 17002ec34544SRui Ueyama // https://sourceware.org/binutils/docs/ld/MEMORY.html 17012ec34544SRui Ueyama // 17022ec34544SRui Ueyama // MEMORY { name [(attr)] : ORIGIN = origin, LENGTH = len ... } 17032ec34544SRui Ueyama void ScriptParser::readMemory() { 17042ec34544SRui Ueyama expect("{"); 1705b8a59c8aSBob Haarman while (!errorCount() && !consume("}")) { 17063837f427SRui Ueyama StringRef tok = next(); 17073837f427SRui Ueyama if (tok == "INCLUDE") { 17082e9d40d5SRui Ueyama readInclude(); 17092e9d40d5SRui Ueyama continue; 17102e9d40d5SRui Ueyama } 17112ec34544SRui Ueyama 17123837f427SRui Ueyama uint32_t flags = 0; 17138cdf1c1eSIgor Kudrin uint32_t invFlags = 0; 17143837f427SRui Ueyama uint32_t negFlags = 0; 17158cdf1c1eSIgor Kudrin uint32_t negInvFlags = 0; 17162ec34544SRui Ueyama if (consume("(")) { 17178cdf1c1eSIgor Kudrin readMemoryAttributes(flags, invFlags, negFlags, negInvFlags); 17182ec34544SRui Ueyama expect(")"); 17192ec34544SRui Ueyama } 17202ec34544SRui Ueyama expect(":"); 17212ec34544SRui Ueyama 172292b5b980SFangrui Song Expr origin = readMemoryAssignment("ORIGIN", "org", "o"); 17232ec34544SRui Ueyama expect(","); 172492b5b980SFangrui Song Expr length = readMemoryAssignment("LENGTH", "len", "l"); 17252ec34544SRui Ueyama 17265f37541cSGeorge Rimar // Add the memory region to the region map. 17278cdf1c1eSIgor Kudrin MemoryRegion *mr = make<MemoryRegion>(tok, origin, length, flags, invFlags, 17288cdf1c1eSIgor Kudrin negFlags, negInvFlags); 17293837f427SRui Ueyama if (!script->memoryRegions.insert({tok, mr}).second) 17303837f427SRui Ueyama setError("region '" + tok + "' already defined"); 17312ec34544SRui Ueyama } 17322ec34544SRui Ueyama } 17332ec34544SRui Ueyama 17342ec34544SRui Ueyama // This function parses the attributes used to match against section 17352ec34544SRui Ueyama // flags when placing output sections in a memory region. These flags 17362ec34544SRui Ueyama // are only used when an explicit memory region name is not used. 17378cdf1c1eSIgor Kudrin void ScriptParser::readMemoryAttributes(uint32_t &flags, uint32_t &invFlags, 17388cdf1c1eSIgor Kudrin uint32_t &negFlags, 17398cdf1c1eSIgor Kudrin uint32_t &negInvFlags) { 17403837f427SRui Ueyama bool invert = false; 17412ec34544SRui Ueyama 17423837f427SRui Ueyama for (char c : next().lower()) { 17438cdf1c1eSIgor Kudrin if (c == '!') { 17443837f427SRui Ueyama invert = !invert; 17458cdf1c1eSIgor Kudrin std::swap(flags, negFlags); 17468cdf1c1eSIgor Kudrin std::swap(invFlags, negInvFlags); 17478cdf1c1eSIgor Kudrin continue; 17482ec34544SRui Ueyama } 17498cdf1c1eSIgor Kudrin if (c == 'w') 17508cdf1c1eSIgor Kudrin flags |= SHF_WRITE; 17518cdf1c1eSIgor Kudrin else if (c == 'x') 17528cdf1c1eSIgor Kudrin flags |= SHF_EXECINSTR; 17538cdf1c1eSIgor Kudrin else if (c == 'a') 17548cdf1c1eSIgor Kudrin flags |= SHF_ALLOC; 17558cdf1c1eSIgor Kudrin else if (c == 'r') 17568cdf1c1eSIgor Kudrin invFlags |= SHF_WRITE; 17578cdf1c1eSIgor Kudrin else 17588cdf1c1eSIgor Kudrin setError("invalid memory region attribute"); 17598cdf1c1eSIgor Kudrin } 17608cdf1c1eSIgor Kudrin 17618cdf1c1eSIgor Kudrin if (invert) { 17628cdf1c1eSIgor Kudrin std::swap(flags, negFlags); 17638cdf1c1eSIgor Kudrin std::swap(invFlags, negInvFlags); 17648cdf1c1eSIgor Kudrin } 17652ec34544SRui Ueyama } 17662ec34544SRui Ueyama 176707837b8fSFangrui Song void elf::readLinkerScript(MemoryBufferRef mb) { 1768439341b9SJames Henderson llvm::TimeTraceScope timeScope("Read linker script", 1769439341b9SJames Henderson mb.getBufferIdentifier()); 17703837f427SRui Ueyama ScriptParser(mb).readLinkerScript(); 17712ec34544SRui Ueyama } 17722ec34544SRui Ueyama 177307837b8fSFangrui Song void elf::readVersionScript(MemoryBufferRef mb) { 1774439341b9SJames Henderson llvm::TimeTraceScope timeScope("Read version script", 1775439341b9SJames Henderson mb.getBufferIdentifier()); 17763837f427SRui Ueyama ScriptParser(mb).readVersionScript(); 17772ec34544SRui Ueyama } 17782ec34544SRui Ueyama 177907837b8fSFangrui Song void elf::readDynamicList(MemoryBufferRef mb) { 1780439341b9SJames Henderson llvm::TimeTraceScope timeScope("Read dynamic list", mb.getBufferIdentifier()); 178107837b8fSFangrui Song ScriptParser(mb).readDynamicList(); 17828c7e8cceSPetr Hosek } 1783bd8cfe65SFangrui Song 178407837b8fSFangrui Song void elf::readDefsym(StringRef name, MemoryBufferRef mb) { 1785439341b9SJames Henderson llvm::TimeTraceScope timeScope("Read defsym input", name); 178607837b8fSFangrui Song ScriptParser(mb).readDefsym(name); 178707837b8fSFangrui Song } 1788