|  | //===- ScriptParser.cpp ---------------------------------------------------===// | 
|  | // | 
|  | //                             The LLVM Linker | 
|  | // | 
|  | // This file is distributed under the University of Illinois Open Source | 
|  | // License. See LICENSE.TXT for details. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | // | 
|  | // This file contains a recursive-descendent parser for linker scripts. | 
|  | // Parsed results are stored to Config and Script global objects. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "ScriptParser.h" | 
|  | #include "Config.h" | 
|  | #include "Driver.h" | 
|  | #include "InputSection.h" | 
|  | #include "LinkerScript.h" | 
|  | #include "OutputSections.h" | 
|  | #include "ScriptLexer.h" | 
|  | #include "Symbols.h" | 
|  | #include "Target.h" | 
|  | #include "lld/Common/Memory.h" | 
|  | #include "llvm/ADT/SmallString.h" | 
|  | #include "llvm/ADT/StringRef.h" | 
|  | #include "llvm/ADT/StringSet.h" | 
|  | #include "llvm/ADT/StringSwitch.h" | 
|  | #include "llvm/BinaryFormat/ELF.h" | 
|  | #include "llvm/Support/Casting.h" | 
|  | #include "llvm/Support/ErrorHandling.h" | 
|  | #include "llvm/Support/FileSystem.h" | 
|  | #include "llvm/Support/Path.h" | 
|  | #include <cassert> | 
|  | #include <limits> | 
|  | #include <vector> | 
|  |  | 
|  | using namespace llvm; | 
|  | using namespace llvm::ELF; | 
|  | using namespace llvm::support::endian; | 
|  | using namespace lld; | 
|  | using namespace lld::elf; | 
|  |  | 
|  | static bool isUnderSysroot(StringRef Path); | 
|  |  | 
|  | namespace { | 
|  | class ScriptParser final : ScriptLexer { | 
|  | public: | 
|  | ScriptParser(MemoryBufferRef MB) | 
|  | : ScriptLexer(MB), | 
|  | IsUnderSysroot(isUnderSysroot(MB.getBufferIdentifier())) {} | 
|  |  | 
|  | void readLinkerScript(); | 
|  | void readVersionScript(); | 
|  | void readDynamicList(); | 
|  | void readDefsym(StringRef Name); | 
|  |  | 
|  | private: | 
|  | void addFile(StringRef Path); | 
|  |  | 
|  | void readAsNeeded(); | 
|  | void readEntry(); | 
|  | void readExtern(); | 
|  | void readGroup(); | 
|  | void readInclude(); | 
|  | void readInput(); | 
|  | void readMemory(); | 
|  | void readOutput(); | 
|  | void readOutputArch(); | 
|  | void readOutputFormat(); | 
|  | void readPhdrs(); | 
|  | void readRegionAlias(); | 
|  | void readSearchDir(); | 
|  | void readSections(); | 
|  | void readTarget(); | 
|  | void readVersion(); | 
|  | void readVersionScriptCommand(); | 
|  |  | 
|  | SymbolAssignment *readSymbolAssignment(StringRef Name); | 
|  | ByteCommand *readByteCommand(StringRef Tok); | 
|  | std::array<uint8_t, 4> readFill(); | 
|  | std::array<uint8_t, 4> parseFill(StringRef Tok); | 
|  | bool readSectionDirective(OutputSection *Cmd, StringRef Tok1, StringRef Tok2); | 
|  | void readSectionAddressType(OutputSection *Cmd); | 
|  | OutputSection *readOverlaySectionDescription(); | 
|  | OutputSection *readOutputSectionDescription(StringRef OutSec); | 
|  | std::vector<BaseCommand *> readOverlay(); | 
|  | std::vector<StringRef> readOutputSectionPhdrs(); | 
|  | InputSectionDescription *readInputSectionDescription(StringRef Tok); | 
|  | StringMatcher readFilePatterns(); | 
|  | std::vector<SectionPattern> readInputSectionsList(); | 
|  | InputSectionDescription *readInputSectionRules(StringRef FilePattern); | 
|  | unsigned readPhdrType(); | 
|  | SortSectionPolicy readSortKind(); | 
|  | SymbolAssignment *readProvideHidden(bool Provide, bool Hidden); | 
|  | SymbolAssignment *readAssignment(StringRef Tok); | 
|  | std::tuple<ELFKind, uint16_t, bool> readBfdName(); | 
|  | void readSort(); | 
|  | Expr readAssert(); | 
|  | Expr readConstant(); | 
|  | Expr getPageSize(); | 
|  |  | 
|  | uint64_t readMemoryAssignment(StringRef, StringRef, StringRef); | 
|  | std::pair<uint32_t, uint32_t> readMemoryAttributes(); | 
|  |  | 
|  | Expr combine(StringRef Op, Expr L, Expr R); | 
|  | Expr readExpr(); | 
|  | Expr readExpr1(Expr Lhs, int MinPrec); | 
|  | StringRef readParenLiteral(); | 
|  | Expr readPrimary(); | 
|  | Expr readTernary(Expr Cond); | 
|  | Expr readParenExpr(); | 
|  |  | 
|  | // For parsing version script. | 
|  | std::vector<SymbolVersion> readVersionExtern(); | 
|  | void readAnonymousDeclaration(); | 
|  | void readVersionDeclaration(StringRef VerStr); | 
|  |  | 
|  | std::pair<std::vector<SymbolVersion>, std::vector<SymbolVersion>> | 
|  | readSymbols(); | 
|  |  | 
|  | // True if a script being read is in a subdirectory specified by -sysroot. | 
|  | bool IsUnderSysroot; | 
|  |  | 
|  | // A set to detect an INCLUDE() cycle. | 
|  | StringSet<> Seen; | 
|  | }; | 
|  | } // namespace | 
|  |  | 
|  | static StringRef unquote(StringRef S) { | 
|  | if (S.startswith("\"")) | 
|  | return S.substr(1, S.size() - 2); | 
|  | return S; | 
|  | } | 
|  |  | 
|  | static bool isUnderSysroot(StringRef Path) { | 
|  | if (Config->Sysroot == "") | 
|  | return false; | 
|  | for (; !Path.empty(); Path = sys::path::parent_path(Path)) | 
|  | if (sys::fs::equivalent(Config->Sysroot, Path)) | 
|  | return true; | 
|  | return false; | 
|  | } | 
|  |  | 
|  | // Some operations only support one non absolute value. Move the | 
|  | // absolute one to the right hand side for convenience. | 
|  | static void moveAbsRight(ExprValue &A, ExprValue &B) { | 
|  | if (A.Sec == nullptr || (A.ForceAbsolute && !B.isAbsolute())) | 
|  | std::swap(A, B); | 
|  | if (!B.isAbsolute()) | 
|  | error(A.Loc + ": at least one side of the expression must be absolute"); | 
|  | } | 
|  |  | 
|  | static ExprValue add(ExprValue A, ExprValue B) { | 
|  | moveAbsRight(A, B); | 
|  | return {A.Sec, A.ForceAbsolute, A.getSectionOffset() + B.getValue(), A.Loc}; | 
|  | } | 
|  |  | 
|  | static ExprValue sub(ExprValue A, ExprValue B) { | 
|  | // The distance between two symbols in sections is absolute. | 
|  | if (!A.isAbsolute() && !B.isAbsolute()) | 
|  | return A.getValue() - B.getValue(); | 
|  | return {A.Sec, false, A.getSectionOffset() - B.getValue(), A.Loc}; | 
|  | } | 
|  |  | 
|  | static ExprValue bitAnd(ExprValue A, ExprValue B) { | 
|  | moveAbsRight(A, B); | 
|  | return {A.Sec, A.ForceAbsolute, | 
|  | (A.getValue() & B.getValue()) - A.getSecAddr(), A.Loc}; | 
|  | } | 
|  |  | 
|  | static ExprValue bitOr(ExprValue A, ExprValue B) { | 
|  | moveAbsRight(A, B); | 
|  | return {A.Sec, A.ForceAbsolute, | 
|  | (A.getValue() | B.getValue()) - A.getSecAddr(), A.Loc}; | 
|  | } | 
|  |  | 
|  | void ScriptParser::readDynamicList() { | 
|  | Config->HasDynamicList = true; | 
|  | expect("{"); | 
|  | std::vector<SymbolVersion> Locals; | 
|  | std::vector<SymbolVersion> Globals; | 
|  | std::tie(Locals, Globals) = readSymbols(); | 
|  | expect(";"); | 
|  |  | 
|  | if (!atEOF()) { | 
|  | setError("EOF expected, but got " + next()); | 
|  | return; | 
|  | } | 
|  | if (!Locals.empty()) { | 
|  | setError("\"local:\" scope not supported in --dynamic-list"); | 
|  | return; | 
|  | } | 
|  |  | 
|  | for (SymbolVersion V : Globals) | 
|  | Config->DynamicList.push_back(V); | 
|  | } | 
|  |  | 
|  | void ScriptParser::readVersionScript() { | 
|  | readVersionScriptCommand(); | 
|  | if (!atEOF()) | 
|  | setError("EOF expected, but got " + next()); | 
|  | } | 
|  |  | 
|  | void ScriptParser::readVersionScriptCommand() { | 
|  | if (consume("{")) { | 
|  | readAnonymousDeclaration(); | 
|  | return; | 
|  | } | 
|  |  | 
|  | while (!atEOF() && !errorCount() && peek() != "}") { | 
|  | StringRef VerStr = next(); | 
|  | if (VerStr == "{") { | 
|  | setError("anonymous version definition is used in " | 
|  | "combination with other version definitions"); | 
|  | return; | 
|  | } | 
|  | expect("{"); | 
|  | readVersionDeclaration(VerStr); | 
|  | } | 
|  | } | 
|  |  | 
|  | void ScriptParser::readVersion() { | 
|  | expect("{"); | 
|  | readVersionScriptCommand(); | 
|  | expect("}"); | 
|  | } | 
|  |  | 
|  | void ScriptParser::readLinkerScript() { | 
|  | while (!atEOF()) { | 
|  | StringRef Tok = next(); | 
|  | if (Tok == ";") | 
|  | continue; | 
|  |  | 
|  | if (Tok == "ENTRY") { | 
|  | readEntry(); | 
|  | } else if (Tok == "EXTERN") { | 
|  | readExtern(); | 
|  | } else if (Tok == "GROUP") { | 
|  | readGroup(); | 
|  | } else if (Tok == "INCLUDE") { | 
|  | readInclude(); | 
|  | } else if (Tok == "INPUT") { | 
|  | readInput(); | 
|  | } else if (Tok == "MEMORY") { | 
|  | readMemory(); | 
|  | } else if (Tok == "OUTPUT") { | 
|  | readOutput(); | 
|  | } else if (Tok == "OUTPUT_ARCH") { | 
|  | readOutputArch(); | 
|  | } else if (Tok == "OUTPUT_FORMAT") { | 
|  | readOutputFormat(); | 
|  | } else if (Tok == "PHDRS") { | 
|  | readPhdrs(); | 
|  | } else if (Tok == "REGION_ALIAS") { | 
|  | readRegionAlias(); | 
|  | } else if (Tok == "SEARCH_DIR") { | 
|  | readSearchDir(); | 
|  | } else if (Tok == "SECTIONS") { | 
|  | readSections(); | 
|  | } else if (Tok == "TARGET") { | 
|  | readTarget(); | 
|  | } else if (Tok == "VERSION") { | 
|  | readVersion(); | 
|  | } else if (SymbolAssignment *Cmd = readAssignment(Tok)) { | 
|  | Script->SectionCommands.push_back(Cmd); | 
|  | } else { | 
|  | setError("unknown directive: " + Tok); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | void ScriptParser::readDefsym(StringRef Name) { | 
|  | if (errorCount()) | 
|  | return; | 
|  | Expr E = readExpr(); | 
|  | if (!atEOF()) | 
|  | setError("EOF expected, but got " + next()); | 
|  | SymbolAssignment *Cmd = make<SymbolAssignment>(Name, E, getCurrentLocation()); | 
|  | Script->SectionCommands.push_back(Cmd); | 
|  | } | 
|  |  | 
|  | void ScriptParser::addFile(StringRef S) { | 
|  | if (IsUnderSysroot && S.startswith("/")) { | 
|  | SmallString<128> PathData; | 
|  | StringRef Path = (Config->Sysroot + S).toStringRef(PathData); | 
|  | if (sys::fs::exists(Path)) { | 
|  | Driver->addFile(Saver.save(Path), /*WithLOption=*/false); | 
|  | return; | 
|  | } | 
|  | } | 
|  |  | 
|  | if (S.startswith("/")) { | 
|  | Driver->addFile(S, /*WithLOption=*/false); | 
|  | } else if (S.startswith("=")) { | 
|  | if (Config->Sysroot.empty()) | 
|  | Driver->addFile(S.substr(1), /*WithLOption=*/false); | 
|  | else | 
|  | Driver->addFile(Saver.save(Config->Sysroot + "/" + S.substr(1)), | 
|  | /*WithLOption=*/false); | 
|  | } else if (S.startswith("-l")) { | 
|  | Driver->addLibrary(S.substr(2)); | 
|  | } else if (sys::fs::exists(S)) { | 
|  | Driver->addFile(S, /*WithLOption=*/false); | 
|  | } else { | 
|  | if (Optional<std::string> Path = findFromSearchPaths(S)) | 
|  | Driver->addFile(Saver.save(*Path), /*WithLOption=*/true); | 
|  | else | 
|  | setError("unable to find " + S); | 
|  | } | 
|  | } | 
|  |  | 
|  | void ScriptParser::readAsNeeded() { | 
|  | expect("("); | 
|  | bool Orig = Config->AsNeeded; | 
|  | Config->AsNeeded = true; | 
|  | while (!errorCount() && !consume(")")) | 
|  | addFile(unquote(next())); | 
|  | Config->AsNeeded = Orig; | 
|  | } | 
|  |  | 
|  | void ScriptParser::readEntry() { | 
|  | // -e <symbol> takes predecence over ENTRY(<symbol>). | 
|  | expect("("); | 
|  | StringRef Tok = next(); | 
|  | if (Config->Entry.empty()) | 
|  | Config->Entry = Tok; | 
|  | expect(")"); | 
|  | } | 
|  |  | 
|  | void ScriptParser::readExtern() { | 
|  | expect("("); | 
|  | while (!errorCount() && !consume(")")) | 
|  | Config->Undefined.push_back(next()); | 
|  | } | 
|  |  | 
|  | void ScriptParser::readGroup() { | 
|  | bool Orig = InputFile::IsInGroup; | 
|  | InputFile::IsInGroup = true; | 
|  | readInput(); | 
|  | InputFile::IsInGroup = Orig; | 
|  | if (!Orig) | 
|  | ++InputFile::NextGroupId; | 
|  | } | 
|  |  | 
|  | void ScriptParser::readInclude() { | 
|  | StringRef Tok = unquote(next()); | 
|  |  | 
|  | if (!Seen.insert(Tok).second) { | 
|  | setError("there is a cycle in linker script INCLUDEs"); | 
|  | return; | 
|  | } | 
|  |  | 
|  | if (Optional<std::string> Path = searchScript(Tok)) { | 
|  | if (Optional<MemoryBufferRef> MB = readFile(*Path)) | 
|  | tokenize(*MB); | 
|  | return; | 
|  | } | 
|  | setError("cannot find linker script " + Tok); | 
|  | } | 
|  |  | 
|  | void ScriptParser::readInput() { | 
|  | expect("("); | 
|  | while (!errorCount() && !consume(")")) { | 
|  | if (consume("AS_NEEDED")) | 
|  | readAsNeeded(); | 
|  | else | 
|  | addFile(unquote(next())); | 
|  | } | 
|  | } | 
|  |  | 
|  | void ScriptParser::readOutput() { | 
|  | // -o <file> takes predecence over OUTPUT(<file>). | 
|  | expect("("); | 
|  | StringRef Tok = next(); | 
|  | if (Config->OutputFile.empty()) | 
|  | Config->OutputFile = unquote(Tok); | 
|  | expect(")"); | 
|  | } | 
|  |  | 
|  | void ScriptParser::readOutputArch() { | 
|  | // OUTPUT_ARCH is ignored for now. | 
|  | expect("("); | 
|  | while (!errorCount() && !consume(")")) | 
|  | skip(); | 
|  | } | 
|  |  | 
|  | std::tuple<ELFKind, uint16_t, bool> ScriptParser::readBfdName() { | 
|  | StringRef S = unquote(next()); | 
|  | if (S == "elf32-i386") | 
|  | return std::make_tuple(ELF32LEKind, EM_386, false); | 
|  | if (S == "elf32-iamcu") | 
|  | return std::make_tuple(ELF32LEKind, EM_IAMCU, false); | 
|  | if (S == "elf32-littlearm") | 
|  | return std::make_tuple(ELF32LEKind, EM_ARM, false); | 
|  | if (S == "elf32-x86-64") | 
|  | return std::make_tuple(ELF32LEKind, EM_X86_64, false); | 
|  | if (S == "elf64-littleaarch64") | 
|  | return std::make_tuple(ELF64LEKind, EM_AARCH64, false); | 
|  | if (S == "elf64-powerpc") | 
|  | return std::make_tuple(ELF64BEKind, EM_PPC64, false); | 
|  | if (S == "elf64-powerpcle") | 
|  | return std::make_tuple(ELF64LEKind, EM_PPC64, false); | 
|  | if (S == "elf64-x86-64") | 
|  | return std::make_tuple(ELF64LEKind, EM_X86_64, false); | 
|  | if (S == "elf32-tradbigmips") | 
|  | return std::make_tuple(ELF32BEKind, EM_MIPS, false); | 
|  | if (S == "elf32-ntradbigmips") | 
|  | return std::make_tuple(ELF32BEKind, EM_MIPS, true); | 
|  | if (S == "elf32-tradlittlemips") | 
|  | return std::make_tuple(ELF32LEKind, EM_MIPS, false); | 
|  | if (S == "elf32-ntradlittlemips") | 
|  | return std::make_tuple(ELF32LEKind, EM_MIPS, true); | 
|  | if (S == "elf64-tradbigmips") | 
|  | return std::make_tuple(ELF64BEKind, EM_MIPS, false); | 
|  | if (S == "elf64-tradlittlemips") | 
|  | return std::make_tuple(ELF64LEKind, EM_MIPS, false); | 
|  |  | 
|  | setError("unknown output format name: " + S); | 
|  | return std::make_tuple(ELFNoneKind, EM_NONE, false); | 
|  | } | 
|  |  | 
|  | // Parse OUTPUT_FORMAT(bfdname) or OUTPUT_FORMAT(bfdname, big, little). | 
|  | // Currently we ignore big and little parameters. | 
|  | void ScriptParser::readOutputFormat() { | 
|  | expect("("); | 
|  |  | 
|  | std::tuple<ELFKind, uint16_t, bool> BfdTuple = readBfdName(); | 
|  | if (Config->EKind == ELFNoneKind) | 
|  | std::tie(Config->EKind, Config->EMachine, Config->MipsN32Abi) = BfdTuple; | 
|  |  | 
|  | if (consume(")")) | 
|  | return; | 
|  | expect(","); | 
|  | skip(); | 
|  | expect(","); | 
|  | skip(); | 
|  | expect(")"); | 
|  | } | 
|  |  | 
|  | void ScriptParser::readPhdrs() { | 
|  | expect("{"); | 
|  |  | 
|  | while (!errorCount() && !consume("}")) { | 
|  | PhdrsCommand Cmd; | 
|  | Cmd.Name = next(); | 
|  | Cmd.Type = readPhdrType(); | 
|  |  | 
|  | while (!errorCount() && !consume(";")) { | 
|  | if (consume("FILEHDR")) | 
|  | Cmd.HasFilehdr = true; | 
|  | else if (consume("PHDRS")) | 
|  | Cmd.HasPhdrs = true; | 
|  | else if (consume("AT")) | 
|  | Cmd.LMAExpr = readParenExpr(); | 
|  | else if (consume("FLAGS")) | 
|  | Cmd.Flags = readParenExpr()().getValue(); | 
|  | else | 
|  | setError("unexpected header attribute: " + next()); | 
|  | } | 
|  |  | 
|  | Script->PhdrsCommands.push_back(Cmd); | 
|  | } | 
|  | } | 
|  |  | 
|  | void ScriptParser::readRegionAlias() { | 
|  | expect("("); | 
|  | StringRef Alias = unquote(next()); | 
|  | expect(","); | 
|  | StringRef Name = next(); | 
|  | expect(")"); | 
|  |  | 
|  | if (Script->MemoryRegions.count(Alias)) | 
|  | setError("redefinition of memory region '" + Alias + "'"); | 
|  | if (!Script->MemoryRegions.count(Name)) | 
|  | setError("memory region '" + Name + "' is not defined"); | 
|  | Script->MemoryRegions.insert({Alias, Script->MemoryRegions[Name]}); | 
|  | } | 
|  |  | 
|  | void ScriptParser::readSearchDir() { | 
|  | expect("("); | 
|  | StringRef Tok = next(); | 
|  | if (!Config->Nostdlib) | 
|  | Config->SearchPaths.push_back(unquote(Tok)); | 
|  | expect(")"); | 
|  | } | 
|  |  | 
|  | // This reads an overlay description. Overlays are used to describe output | 
|  | // sections that use the same virtual memory range and normally would trigger | 
|  | // linker's sections sanity check failures. | 
|  | // https://sourceware.org/binutils/docs/ld/Overlay-Description.html#Overlay-Description | 
|  | std::vector<BaseCommand *> ScriptParser::readOverlay() { | 
|  | // VA and LMA expressions are optional, though for simplicity of | 
|  | // implementation we assume they are not. That is what OVERLAY was designed | 
|  | // for first of all: to allow sections with overlapping VAs at different LMAs. | 
|  | Expr AddrExpr = readExpr(); | 
|  | expect(":"); | 
|  | expect("AT"); | 
|  | Expr LMAExpr = readParenExpr(); | 
|  | expect("{"); | 
|  |  | 
|  | std::vector<BaseCommand *> V; | 
|  | OutputSection *Prev = nullptr; | 
|  | while (!errorCount() && !consume("}")) { | 
|  | // VA is the same for all sections. The LMAs are consecutive in memory | 
|  | // starting from the base load address specified. | 
|  | OutputSection *OS = readOverlaySectionDescription(); | 
|  | OS->AddrExpr = AddrExpr; | 
|  | if (Prev) | 
|  | OS->LMAExpr = [=] { return Prev->getLMA() + Prev->Size; }; | 
|  | else | 
|  | OS->LMAExpr = LMAExpr; | 
|  | V.push_back(OS); | 
|  | Prev = OS; | 
|  | } | 
|  |  | 
|  | // According to the specification, at the end of the overlay, the location | 
|  | // counter should be equal to the overlay base address plus size of the | 
|  | // largest section seen in the overlay. | 
|  | // Here we want to create the Dot assignment command to achieve that. | 
|  | Expr MoveDot = [=] { | 
|  | uint64_t Max = 0; | 
|  | for (BaseCommand *Cmd : V) | 
|  | Max = std::max(Max, cast<OutputSection>(Cmd)->Size); | 
|  | return AddrExpr().getValue() + Max; | 
|  | }; | 
|  | V.push_back(make<SymbolAssignment>(".", MoveDot, getCurrentLocation())); | 
|  | return V; | 
|  | } | 
|  |  | 
|  | void ScriptParser::readSections() { | 
|  | Script->HasSectionsCommand = true; | 
|  |  | 
|  | // -no-rosegment is used to avoid placing read only non-executable sections in | 
|  | // their own segment. We do the same if SECTIONS command is present in linker | 
|  | // script. See comment for computeFlags(). | 
|  | Config->SingleRoRx = true; | 
|  |  | 
|  | expect("{"); | 
|  | std::vector<BaseCommand *> V; | 
|  | while (!errorCount() && !consume("}")) { | 
|  | StringRef Tok = next(); | 
|  | if (Tok == "OVERLAY") { | 
|  | for (BaseCommand *Cmd : readOverlay()) | 
|  | V.push_back(Cmd); | 
|  | continue; | 
|  | } else if (Tok == "INCLUDE") { | 
|  | readInclude(); | 
|  | continue; | 
|  | } | 
|  |  | 
|  | if (BaseCommand *Cmd = readAssignment(Tok)) | 
|  | V.push_back(Cmd); | 
|  | else | 
|  | V.push_back(readOutputSectionDescription(Tok)); | 
|  | } | 
|  |  | 
|  | if (!atEOF() && consume("INSERT")) { | 
|  | std::vector<BaseCommand *> *Dest = nullptr; | 
|  | if (consume("AFTER")) | 
|  | Dest = &Script->InsertAfterCommands[next()]; | 
|  | else if (consume("BEFORE")) | 
|  | Dest = &Script->InsertBeforeCommands[next()]; | 
|  | else | 
|  | setError("expected AFTER/BEFORE, but got '" + next() + "'"); | 
|  | if (Dest) | 
|  | Dest->insert(Dest->end(), V.begin(), V.end()); | 
|  | return; | 
|  | } | 
|  |  | 
|  | Script->SectionCommands.insert(Script->SectionCommands.end(), V.begin(), | 
|  | V.end()); | 
|  | } | 
|  |  | 
|  | void ScriptParser::readTarget() { | 
|  | // TARGET(foo) is an alias for "--format foo". Unlike GNU linkers, | 
|  | // we accept only a limited set of BFD names (i.e. "elf" or "binary") | 
|  | // for --format. We recognize only /^elf/ and "binary" in the linker | 
|  | // script as well. | 
|  | expect("("); | 
|  | StringRef Tok = next(); | 
|  | expect(")"); | 
|  |  | 
|  | if (Tok.startswith("elf")) | 
|  | Config->FormatBinary = false; | 
|  | else if (Tok == "binary") | 
|  | Config->FormatBinary = true; | 
|  | else | 
|  | setError("unknown target: " + Tok); | 
|  | } | 
|  |  | 
|  | static int precedence(StringRef Op) { | 
|  | return StringSwitch<int>(Op) | 
|  | .Cases("*", "/", "%", 8) | 
|  | .Cases("+", "-", 7) | 
|  | .Cases("<<", ">>", 6) | 
|  | .Cases("<", "<=", ">", ">=", "==", "!=", 5) | 
|  | .Case("&", 4) | 
|  | .Case("|", 3) | 
|  | .Case("&&", 2) | 
|  | .Case("||", 1) | 
|  | .Default(-1); | 
|  | } | 
|  |  | 
|  | StringMatcher ScriptParser::readFilePatterns() { | 
|  | std::vector<StringRef> V; | 
|  | while (!errorCount() && !consume(")")) | 
|  | V.push_back(next()); | 
|  | return StringMatcher(V); | 
|  | } | 
|  |  | 
|  | SortSectionPolicy ScriptParser::readSortKind() { | 
|  | if (consume("SORT") || consume("SORT_BY_NAME")) | 
|  | return SortSectionPolicy::Name; | 
|  | if (consume("SORT_BY_ALIGNMENT")) | 
|  | return SortSectionPolicy::Alignment; | 
|  | if (consume("SORT_BY_INIT_PRIORITY")) | 
|  | return SortSectionPolicy::Priority; | 
|  | if (consume("SORT_NONE")) | 
|  | return SortSectionPolicy::None; | 
|  | return SortSectionPolicy::Default; | 
|  | } | 
|  |  | 
|  | // Reads SECTIONS command contents in the following form: | 
|  | // | 
|  | // <contents> ::= <elem>* | 
|  | // <elem>     ::= <exclude>? <glob-pattern> | 
|  | // <exclude>  ::= "EXCLUDE_FILE" "(" <glob-pattern>+ ")" | 
|  | // | 
|  | // For example, | 
|  | // | 
|  | // *(.foo EXCLUDE_FILE (a.o) .bar EXCLUDE_FILE (b.o) .baz) | 
|  | // | 
|  | // is parsed as ".foo", ".bar" with "a.o", and ".baz" with "b.o". | 
|  | // The semantics of that is section .foo in any file, section .bar in | 
|  | // any file but a.o, and section .baz in any file but b.o. | 
|  | std::vector<SectionPattern> ScriptParser::readInputSectionsList() { | 
|  | std::vector<SectionPattern> Ret; | 
|  | while (!errorCount() && peek() != ")") { | 
|  | StringMatcher ExcludeFilePat; | 
|  | if (consume("EXCLUDE_FILE")) { | 
|  | expect("("); | 
|  | ExcludeFilePat = readFilePatterns(); | 
|  | } | 
|  |  | 
|  | std::vector<StringRef> V; | 
|  | while (!errorCount() && peek() != ")" && peek() != "EXCLUDE_FILE") | 
|  | V.push_back(next()); | 
|  |  | 
|  | if (!V.empty()) | 
|  | Ret.push_back({std::move(ExcludeFilePat), StringMatcher(V)}); | 
|  | else | 
|  | setError("section pattern is expected"); | 
|  | } | 
|  | return Ret; | 
|  | } | 
|  |  | 
|  | // Reads contents of "SECTIONS" directive. That directive contains a | 
|  | // list of glob patterns for input sections. The grammar is as follows. | 
|  | // | 
|  | // <patterns> ::= <section-list> | 
|  | //              | <sort> "(" <section-list> ")" | 
|  | //              | <sort> "(" <sort> "(" <section-list> ")" ")" | 
|  | // | 
|  | // <sort>     ::= "SORT" | "SORT_BY_NAME" | "SORT_BY_ALIGNMENT" | 
|  | //              | "SORT_BY_INIT_PRIORITY" | "SORT_NONE" | 
|  | // | 
|  | // <section-list> is parsed by readInputSectionsList(). | 
|  | InputSectionDescription * | 
|  | ScriptParser::readInputSectionRules(StringRef FilePattern) { | 
|  | auto *Cmd = make<InputSectionDescription>(FilePattern); | 
|  | expect("("); | 
|  |  | 
|  | while (!errorCount() && !consume(")")) { | 
|  | SortSectionPolicy Outer = readSortKind(); | 
|  | SortSectionPolicy Inner = SortSectionPolicy::Default; | 
|  | std::vector<SectionPattern> V; | 
|  | if (Outer != SortSectionPolicy::Default) { | 
|  | expect("("); | 
|  | Inner = readSortKind(); | 
|  | if (Inner != SortSectionPolicy::Default) { | 
|  | expect("("); | 
|  | V = readInputSectionsList(); | 
|  | expect(")"); | 
|  | } else { | 
|  | V = readInputSectionsList(); | 
|  | } | 
|  | expect(")"); | 
|  | } else { | 
|  | V = readInputSectionsList(); | 
|  | } | 
|  |  | 
|  | for (SectionPattern &Pat : V) { | 
|  | Pat.SortInner = Inner; | 
|  | Pat.SortOuter = Outer; | 
|  | } | 
|  |  | 
|  | std::move(V.begin(), V.end(), std::back_inserter(Cmd->SectionPatterns)); | 
|  | } | 
|  | return Cmd; | 
|  | } | 
|  |  | 
|  | InputSectionDescription * | 
|  | ScriptParser::readInputSectionDescription(StringRef Tok) { | 
|  | // Input section wildcard can be surrounded by KEEP. | 
|  | // https://sourceware.org/binutils/docs/ld/Input-Section-Keep.html#Input-Section-Keep | 
|  | if (Tok == "KEEP") { | 
|  | expect("("); | 
|  | StringRef FilePattern = next(); | 
|  | InputSectionDescription *Cmd = readInputSectionRules(FilePattern); | 
|  | expect(")"); | 
|  | Script->KeptSections.push_back(Cmd); | 
|  | return Cmd; | 
|  | } | 
|  | return readInputSectionRules(Tok); | 
|  | } | 
|  |  | 
|  | void ScriptParser::readSort() { | 
|  | expect("("); | 
|  | expect("CONSTRUCTORS"); | 
|  | expect(")"); | 
|  | } | 
|  |  | 
|  | Expr ScriptParser::readAssert() { | 
|  | expect("("); | 
|  | Expr E = readExpr(); | 
|  | expect(","); | 
|  | StringRef Msg = unquote(next()); | 
|  | expect(")"); | 
|  |  | 
|  | return [=] { | 
|  | if (!E().getValue()) | 
|  | error(Msg); | 
|  | return Script->getDot(); | 
|  | }; | 
|  | } | 
|  |  | 
|  | // Reads a FILL(expr) command. We handle the FILL command as an | 
|  | // alias for =fillexp section attribute, which is different from | 
|  | // what GNU linkers do. | 
|  | // https://sourceware.org/binutils/docs/ld/Output-Section-Data.html | 
|  | std::array<uint8_t, 4> ScriptParser::readFill() { | 
|  | expect("("); | 
|  | std::array<uint8_t, 4> V = parseFill(next()); | 
|  | expect(")"); | 
|  | return V; | 
|  | } | 
|  |  | 
|  | // Tries to read the special directive for an output section definition which | 
|  | // can be one of following: "(NOLOAD)", "(COPY)", "(INFO)" or "(OVERLAY)". | 
|  | // Tok1 and Tok2 are next 2 tokens peeked. See comment for readSectionAddressType below. | 
|  | bool ScriptParser::readSectionDirective(OutputSection *Cmd, StringRef Tok1, StringRef Tok2) { | 
|  | if (Tok1 != "(") | 
|  | return false; | 
|  | if (Tok2 != "NOLOAD" && Tok2 != "COPY" && Tok2 != "INFO" && Tok2 != "OVERLAY") | 
|  | return false; | 
|  |  | 
|  | expect("("); | 
|  | if (consume("NOLOAD")) { | 
|  | Cmd->Noload = true; | 
|  | } else { | 
|  | skip(); // This is "COPY", "INFO" or "OVERLAY". | 
|  | Cmd->NonAlloc = true; | 
|  | } | 
|  | expect(")"); | 
|  | return true; | 
|  | } | 
|  |  | 
|  | // Reads an expression and/or the special directive for an output | 
|  | // section definition. Directive is one of following: "(NOLOAD)", | 
|  | // "(COPY)", "(INFO)" or "(OVERLAY)". | 
|  | // | 
|  | // An output section name can be followed by an address expression | 
|  | // and/or directive. This grammar is not LL(1) because "(" can be | 
|  | // interpreted as either the beginning of some expression or beginning | 
|  | // of directive. | 
|  | // | 
|  | // https://sourceware.org/binutils/docs/ld/Output-Section-Address.html | 
|  | // https://sourceware.org/binutils/docs/ld/Output-Section-Type.html | 
|  | void ScriptParser::readSectionAddressType(OutputSection *Cmd) { | 
|  | if (readSectionDirective(Cmd, peek(), peek2())) | 
|  | return; | 
|  |  | 
|  | Cmd->AddrExpr = readExpr(); | 
|  | if (peek() == "(" && !readSectionDirective(Cmd, "(", peek2())) | 
|  | setError("unknown section directive: " + peek2()); | 
|  | } | 
|  |  | 
|  | static Expr checkAlignment(Expr E, std::string &Loc) { | 
|  | return [=] { | 
|  | uint64_t Alignment = std::max((uint64_t)1, E().getValue()); | 
|  | if (!isPowerOf2_64(Alignment)) { | 
|  | error(Loc + ": alignment must be power of 2"); | 
|  | return (uint64_t)1; // Return a dummy value. | 
|  | } | 
|  | return Alignment; | 
|  | }; | 
|  | } | 
|  |  | 
|  | OutputSection *ScriptParser::readOverlaySectionDescription() { | 
|  | OutputSection *Cmd = | 
|  | Script->createOutputSection(next(), getCurrentLocation()); | 
|  | Cmd->InOverlay = true; | 
|  | expect("{"); | 
|  | while (!errorCount() && !consume("}")) | 
|  | Cmd->SectionCommands.push_back(readInputSectionRules(next())); | 
|  | Cmd->Phdrs = readOutputSectionPhdrs(); | 
|  | return Cmd; | 
|  | } | 
|  |  | 
|  | OutputSection *ScriptParser::readOutputSectionDescription(StringRef OutSec) { | 
|  | OutputSection *Cmd = | 
|  | Script->createOutputSection(OutSec, getCurrentLocation()); | 
|  |  | 
|  | size_t SymbolsReferenced = Script->ReferencedSymbols.size(); | 
|  |  | 
|  | if (peek() != ":") | 
|  | readSectionAddressType(Cmd); | 
|  | expect(":"); | 
|  |  | 
|  | std::string Location = getCurrentLocation(); | 
|  | if (consume("AT")) | 
|  | Cmd->LMAExpr = readParenExpr(); | 
|  | if (consume("ALIGN")) | 
|  | Cmd->AlignExpr = checkAlignment(readParenExpr(), Location); | 
|  | if (consume("SUBALIGN")) | 
|  | Cmd->SubalignExpr = checkAlignment(readParenExpr(), Location); | 
|  |  | 
|  | // Parse constraints. | 
|  | if (consume("ONLY_IF_RO")) | 
|  | Cmd->Constraint = ConstraintKind::ReadOnly; | 
|  | if (consume("ONLY_IF_RW")) | 
|  | Cmd->Constraint = ConstraintKind::ReadWrite; | 
|  | expect("{"); | 
|  |  | 
|  | while (!errorCount() && !consume("}")) { | 
|  | StringRef Tok = next(); | 
|  | if (Tok == ";") { | 
|  | // Empty commands are allowed. Do nothing here. | 
|  | } else if (SymbolAssignment *Assign = readAssignment(Tok)) { | 
|  | Cmd->SectionCommands.push_back(Assign); | 
|  | } else if (ByteCommand *Data = readByteCommand(Tok)) { | 
|  | Cmd->SectionCommands.push_back(Data); | 
|  | } else if (Tok == "CONSTRUCTORS") { | 
|  | // CONSTRUCTORS is a keyword to make the linker recognize C++ ctors/dtors | 
|  | // by name. This is for very old file formats such as ECOFF/XCOFF. | 
|  | // For ELF, we should ignore. | 
|  | } else if (Tok == "FILL") { | 
|  | Cmd->Filler = readFill(); | 
|  | } else if (Tok == "SORT") { | 
|  | readSort(); | 
|  | } else if (Tok == "INCLUDE") { | 
|  | readInclude(); | 
|  | } else if (peek() == "(") { | 
|  | Cmd->SectionCommands.push_back(readInputSectionDescription(Tok)); | 
|  | } else { | 
|  | // We have a file name and no input sections description. It is not a | 
|  | // commonly used syntax, but still acceptable. In that case, all sections | 
|  | // from the file will be included. | 
|  | auto *ISD = make<InputSectionDescription>(Tok); | 
|  | ISD->SectionPatterns.push_back({{}, StringMatcher({"*"})}); | 
|  | Cmd->SectionCommands.push_back(ISD); | 
|  | } | 
|  | } | 
|  |  | 
|  | if (consume(">")) | 
|  | Cmd->MemoryRegionName = next(); | 
|  |  | 
|  | if (consume("AT")) { | 
|  | expect(">"); | 
|  | Cmd->LMARegionName = next(); | 
|  | } | 
|  |  | 
|  | if (Cmd->LMAExpr && !Cmd->LMARegionName.empty()) | 
|  | error("section can't have both LMA and a load region"); | 
|  |  | 
|  | Cmd->Phdrs = readOutputSectionPhdrs(); | 
|  |  | 
|  | if (consume("=")) | 
|  | Cmd->Filler = parseFill(next()); | 
|  | else if (peek().startswith("=")) | 
|  | Cmd->Filler = parseFill(next().drop_front()); | 
|  |  | 
|  | // Consume optional comma following output section command. | 
|  | consume(","); | 
|  |  | 
|  | if (Script->ReferencedSymbols.size() > SymbolsReferenced) | 
|  | Cmd->ExpressionsUseSymbols = true; | 
|  | return Cmd; | 
|  | } | 
|  |  | 
|  | // Parses a given string as a octal/decimal/hexadecimal number and | 
|  | // returns it as a big-endian number. Used for `=<fillexp>`. | 
|  | // https://sourceware.org/binutils/docs/ld/Output-Section-Fill.html | 
|  | // | 
|  | // When reading a hexstring, ld.bfd handles it as a blob of arbitrary | 
|  | // size, while ld.gold always handles it as a 32-bit big-endian number. | 
|  | // We are compatible with ld.gold because it's easier to implement. | 
|  | std::array<uint8_t, 4> ScriptParser::parseFill(StringRef Tok) { | 
|  | uint32_t V = 0; | 
|  | if (!to_integer(Tok, V)) | 
|  | setError("invalid filler expression: " + Tok); | 
|  |  | 
|  | std::array<uint8_t, 4> Buf; | 
|  | write32be(Buf.data(), V); | 
|  | return Buf; | 
|  | } | 
|  |  | 
|  | SymbolAssignment *ScriptParser::readProvideHidden(bool Provide, bool Hidden) { | 
|  | expect("("); | 
|  | SymbolAssignment *Cmd = readSymbolAssignment(next()); | 
|  | Cmd->Provide = Provide; | 
|  | Cmd->Hidden = Hidden; | 
|  | expect(")"); | 
|  | return Cmd; | 
|  | } | 
|  |  | 
|  | SymbolAssignment *ScriptParser::readAssignment(StringRef Tok) { | 
|  | // Assert expression returns Dot, so this is equal to ".=." | 
|  | if (Tok == "ASSERT") | 
|  | return make<SymbolAssignment>(".", readAssert(), getCurrentLocation()); | 
|  |  | 
|  | size_t OldPos = Pos; | 
|  | SymbolAssignment *Cmd = nullptr; | 
|  | if (peek() == "=" || peek() == "+=") | 
|  | Cmd = readSymbolAssignment(Tok); | 
|  | else if (Tok == "PROVIDE") | 
|  | Cmd = readProvideHidden(true, false); | 
|  | else if (Tok == "HIDDEN") | 
|  | Cmd = readProvideHidden(false, true); | 
|  | else if (Tok == "PROVIDE_HIDDEN") | 
|  | Cmd = readProvideHidden(true, true); | 
|  |  | 
|  | if (Cmd) { | 
|  | Cmd->CommandString = | 
|  | Tok.str() + " " + | 
|  | llvm::join(Tokens.begin() + OldPos, Tokens.begin() + Pos, " "); | 
|  | expect(";"); | 
|  | } | 
|  | return Cmd; | 
|  | } | 
|  |  | 
|  | SymbolAssignment *ScriptParser::readSymbolAssignment(StringRef Name) { | 
|  | StringRef Op = next(); | 
|  | assert(Op == "=" || Op == "+="); | 
|  | Expr E = readExpr(); | 
|  | if (Op == "+=") { | 
|  | std::string Loc = getCurrentLocation(); | 
|  | E = [=] { return add(Script->getSymbolValue(Name, Loc), E()); }; | 
|  | } | 
|  | return make<SymbolAssignment>(Name, E, getCurrentLocation()); | 
|  | } | 
|  |  | 
|  | // This is an operator-precedence parser to parse a linker | 
|  | // script expression. | 
|  | Expr ScriptParser::readExpr() { | 
|  | // Our lexer is context-aware. Set the in-expression bit so that | 
|  | // they apply different tokenization rules. | 
|  | bool Orig = InExpr; | 
|  | InExpr = true; | 
|  | Expr E = readExpr1(readPrimary(), 0); | 
|  | InExpr = Orig; | 
|  | return E; | 
|  | } | 
|  |  | 
|  | Expr ScriptParser::combine(StringRef Op, Expr L, Expr R) { | 
|  | if (Op == "+") | 
|  | return [=] { return add(L(), R()); }; | 
|  | if (Op == "-") | 
|  | return [=] { return sub(L(), R()); }; | 
|  | if (Op == "*") | 
|  | return [=] { return L().getValue() * R().getValue(); }; | 
|  | if (Op == "/") { | 
|  | std::string Loc = getCurrentLocation(); | 
|  | return [=]() -> uint64_t { | 
|  | if (uint64_t RV = R().getValue()) | 
|  | return L().getValue() / RV; | 
|  | error(Loc + ": division by zero"); | 
|  | return 0; | 
|  | }; | 
|  | } | 
|  | if (Op == "%") { | 
|  | std::string Loc = getCurrentLocation(); | 
|  | return [=]() -> uint64_t { | 
|  | if (uint64_t RV = R().getValue()) | 
|  | return L().getValue() % RV; | 
|  | error(Loc + ": modulo by zero"); | 
|  | return 0; | 
|  | }; | 
|  | } | 
|  | if (Op == "<<") | 
|  | return [=] { return L().getValue() << R().getValue(); }; | 
|  | if (Op == ">>") | 
|  | return [=] { return L().getValue() >> R().getValue(); }; | 
|  | if (Op == "<") | 
|  | return [=] { return L().getValue() < R().getValue(); }; | 
|  | if (Op == ">") | 
|  | return [=] { return L().getValue() > R().getValue(); }; | 
|  | if (Op == ">=") | 
|  | return [=] { return L().getValue() >= R().getValue(); }; | 
|  | if (Op == "<=") | 
|  | return [=] { return L().getValue() <= R().getValue(); }; | 
|  | if (Op == "==") | 
|  | return [=] { return L().getValue() == R().getValue(); }; | 
|  | if (Op == "!=") | 
|  | return [=] { return L().getValue() != R().getValue(); }; | 
|  | if (Op == "||") | 
|  | return [=] { return L().getValue() || R().getValue(); }; | 
|  | if (Op == "&&") | 
|  | return [=] { return L().getValue() && R().getValue(); }; | 
|  | if (Op == "&") | 
|  | return [=] { return bitAnd(L(), R()); }; | 
|  | if (Op == "|") | 
|  | return [=] { return bitOr(L(), R()); }; | 
|  | llvm_unreachable("invalid operator"); | 
|  | } | 
|  |  | 
|  | // This is a part of the operator-precedence parser. This function | 
|  | // assumes that the remaining token stream starts with an operator. | 
|  | Expr ScriptParser::readExpr1(Expr Lhs, int MinPrec) { | 
|  | while (!atEOF() && !errorCount()) { | 
|  | // Read an operator and an expression. | 
|  | if (consume("?")) | 
|  | return readTernary(Lhs); | 
|  | StringRef Op1 = peek(); | 
|  | if (precedence(Op1) < MinPrec) | 
|  | break; | 
|  | skip(); | 
|  | Expr Rhs = readPrimary(); | 
|  |  | 
|  | // Evaluate the remaining part of the expression first if the | 
|  | // next operator has greater precedence than the previous one. | 
|  | // For example, if we have read "+" and "3", and if the next | 
|  | // operator is "*", then we'll evaluate 3 * ... part first. | 
|  | while (!atEOF()) { | 
|  | StringRef Op2 = peek(); | 
|  | if (precedence(Op2) <= precedence(Op1)) | 
|  | break; | 
|  | Rhs = readExpr1(Rhs, precedence(Op2)); | 
|  | } | 
|  |  | 
|  | Lhs = combine(Op1, Lhs, Rhs); | 
|  | } | 
|  | return Lhs; | 
|  | } | 
|  |  | 
|  | Expr ScriptParser::getPageSize() { | 
|  | std::string Location = getCurrentLocation(); | 
|  | return [=]() -> uint64_t { | 
|  | if (Target) | 
|  | return Target->PageSize; | 
|  | error(Location + ": unable to calculate page size"); | 
|  | return 4096; // Return a dummy value. | 
|  | }; | 
|  | } | 
|  |  | 
|  | Expr ScriptParser::readConstant() { | 
|  | StringRef S = readParenLiteral(); | 
|  | if (S == "COMMONPAGESIZE") | 
|  | return getPageSize(); | 
|  | if (S == "MAXPAGESIZE") | 
|  | return [] { return Config->MaxPageSize; }; | 
|  | setError("unknown constant: " + S); | 
|  | return [] { return 0; }; | 
|  | } | 
|  |  | 
|  | // Parses Tok as an integer. It recognizes hexadecimal (prefixed with | 
|  | // "0x" or suffixed with "H") and decimal numbers. Decimal numbers may | 
|  | // have "K" (Ki) or "M" (Mi) suffixes. | 
|  | static Optional<uint64_t> parseInt(StringRef Tok) { | 
|  | // Hexadecimal | 
|  | uint64_t Val; | 
|  | if (Tok.startswith_lower("0x")) { | 
|  | if (!to_integer(Tok.substr(2), Val, 16)) | 
|  | return None; | 
|  | return Val; | 
|  | } | 
|  | if (Tok.endswith_lower("H")) { | 
|  | if (!to_integer(Tok.drop_back(), Val, 16)) | 
|  | return None; | 
|  | return Val; | 
|  | } | 
|  |  | 
|  | // Decimal | 
|  | if (Tok.endswith_lower("K")) { | 
|  | if (!to_integer(Tok.drop_back(), Val, 10)) | 
|  | return None; | 
|  | return Val * 1024; | 
|  | } | 
|  | if (Tok.endswith_lower("M")) { | 
|  | if (!to_integer(Tok.drop_back(), Val, 10)) | 
|  | return None; | 
|  | return Val * 1024 * 1024; | 
|  | } | 
|  | if (!to_integer(Tok, Val, 10)) | 
|  | return None; | 
|  | return Val; | 
|  | } | 
|  |  | 
|  | ByteCommand *ScriptParser::readByteCommand(StringRef Tok) { | 
|  | int Size = StringSwitch<int>(Tok) | 
|  | .Case("BYTE", 1) | 
|  | .Case("SHORT", 2) | 
|  | .Case("LONG", 4) | 
|  | .Case("QUAD", 8) | 
|  | .Default(-1); | 
|  | if (Size == -1) | 
|  | return nullptr; | 
|  |  | 
|  | size_t OldPos = Pos; | 
|  | Expr E = readParenExpr(); | 
|  | std::string CommandString = | 
|  | Tok.str() + " " + | 
|  | llvm::join(Tokens.begin() + OldPos, Tokens.begin() + Pos, " "); | 
|  | return make<ByteCommand>(E, Size, CommandString); | 
|  | } | 
|  |  | 
|  | StringRef ScriptParser::readParenLiteral() { | 
|  | expect("("); | 
|  | bool Orig = InExpr; | 
|  | InExpr = false; | 
|  | StringRef Tok = next(); | 
|  | InExpr = Orig; | 
|  | expect(")"); | 
|  | return Tok; | 
|  | } | 
|  |  | 
|  | static void checkIfExists(OutputSection *Cmd, StringRef Location) { | 
|  | if (Cmd->Location.empty() && Script->ErrorOnMissingSection) | 
|  | error(Location + ": undefined section " + Cmd->Name); | 
|  | } | 
|  |  | 
|  | Expr ScriptParser::readPrimary() { | 
|  | if (peek() == "(") | 
|  | return readParenExpr(); | 
|  |  | 
|  | if (consume("~")) { | 
|  | Expr E = readPrimary(); | 
|  | return [=] { return ~E().getValue(); }; | 
|  | } | 
|  | if (consume("!")) { | 
|  | Expr E = readPrimary(); | 
|  | return [=] { return !E().getValue(); }; | 
|  | } | 
|  | if (consume("-")) { | 
|  | Expr E = readPrimary(); | 
|  | return [=] { return -E().getValue(); }; | 
|  | } | 
|  |  | 
|  | StringRef Tok = next(); | 
|  | std::string Location = getCurrentLocation(); | 
|  |  | 
|  | // Built-in functions are parsed here. | 
|  | // https://sourceware.org/binutils/docs/ld/Builtin-Functions.html. | 
|  | if (Tok == "ABSOLUTE") { | 
|  | Expr Inner = readParenExpr(); | 
|  | return [=] { | 
|  | ExprValue I = Inner(); | 
|  | I.ForceAbsolute = true; | 
|  | return I; | 
|  | }; | 
|  | } | 
|  | if (Tok == "ADDR") { | 
|  | StringRef Name = readParenLiteral(); | 
|  | OutputSection *Sec = Script->getOrCreateOutputSection(Name); | 
|  | return [=]() -> ExprValue { | 
|  | checkIfExists(Sec, Location); | 
|  | return {Sec, false, 0, Location}; | 
|  | }; | 
|  | } | 
|  | if (Tok == "ALIGN") { | 
|  | expect("("); | 
|  | Expr E = readExpr(); | 
|  | if (consume(")")) { | 
|  | E = checkAlignment(E, Location); | 
|  | return [=] { return alignTo(Script->getDot(), E().getValue()); }; | 
|  | } | 
|  | expect(","); | 
|  | Expr E2 = checkAlignment(readExpr(), Location); | 
|  | expect(")"); | 
|  | return [=] { | 
|  | ExprValue V = E(); | 
|  | V.Alignment = E2().getValue(); | 
|  | return V; | 
|  | }; | 
|  | } | 
|  | if (Tok == "ALIGNOF") { | 
|  | StringRef Name = readParenLiteral(); | 
|  | OutputSection *Cmd = Script->getOrCreateOutputSection(Name); | 
|  | return [=] { | 
|  | checkIfExists(Cmd, Location); | 
|  | return Cmd->Alignment; | 
|  | }; | 
|  | } | 
|  | if (Tok == "ASSERT") | 
|  | return readAssert(); | 
|  | if (Tok == "CONSTANT") | 
|  | return readConstant(); | 
|  | if (Tok == "DATA_SEGMENT_ALIGN") { | 
|  | expect("("); | 
|  | Expr E = readExpr(); | 
|  | expect(","); | 
|  | readExpr(); | 
|  | expect(")"); | 
|  | return [=] { | 
|  | return alignTo(Script->getDot(), std::max((uint64_t)1, E().getValue())); | 
|  | }; | 
|  | } | 
|  | if (Tok == "DATA_SEGMENT_END") { | 
|  | expect("("); | 
|  | expect("."); | 
|  | expect(")"); | 
|  | return [] { return Script->getDot(); }; | 
|  | } | 
|  | if (Tok == "DATA_SEGMENT_RELRO_END") { | 
|  | // GNU linkers implements more complicated logic to handle | 
|  | // DATA_SEGMENT_RELRO_END. We instead ignore the arguments and | 
|  | // just align to the next page boundary for simplicity. | 
|  | expect("("); | 
|  | readExpr(); | 
|  | expect(","); | 
|  | readExpr(); | 
|  | expect(")"); | 
|  | Expr E = getPageSize(); | 
|  | return [=] { return alignTo(Script->getDot(), E().getValue()); }; | 
|  | } | 
|  | if (Tok == "DEFINED") { | 
|  | StringRef Name = readParenLiteral(); | 
|  | return [=] { return Symtab->find(Name) ? 1 : 0; }; | 
|  | } | 
|  | if (Tok == "LENGTH") { | 
|  | StringRef Name = readParenLiteral(); | 
|  | if (Script->MemoryRegions.count(Name) == 0) { | 
|  | setError("memory region not defined: " + Name); | 
|  | return [] { return 0; }; | 
|  | } | 
|  | return [=] { return Script->MemoryRegions[Name]->Length; }; | 
|  | } | 
|  | if (Tok == "LOADADDR") { | 
|  | StringRef Name = readParenLiteral(); | 
|  | OutputSection *Cmd = Script->getOrCreateOutputSection(Name); | 
|  | return [=] { | 
|  | checkIfExists(Cmd, Location); | 
|  | return Cmd->getLMA(); | 
|  | }; | 
|  | } | 
|  | if (Tok == "MAX" || Tok == "MIN") { | 
|  | expect("("); | 
|  | Expr A = readExpr(); | 
|  | expect(","); | 
|  | Expr B = readExpr(); | 
|  | expect(")"); | 
|  | if (Tok == "MIN") | 
|  | return [=] { return std::min(A().getValue(), B().getValue()); }; | 
|  | return [=] { return std::max(A().getValue(), B().getValue()); }; | 
|  | } | 
|  | if (Tok == "ORIGIN") { | 
|  | StringRef Name = readParenLiteral(); | 
|  | if (Script->MemoryRegions.count(Name) == 0) { | 
|  | setError("memory region not defined: " + Name); | 
|  | return [] { return 0; }; | 
|  | } | 
|  | return [=] { return Script->MemoryRegions[Name]->Origin; }; | 
|  | } | 
|  | if (Tok == "SEGMENT_START") { | 
|  | expect("("); | 
|  | skip(); | 
|  | expect(","); | 
|  | Expr E = readExpr(); | 
|  | expect(")"); | 
|  | return [=] { return E(); }; | 
|  | } | 
|  | if (Tok == "SIZEOF") { | 
|  | StringRef Name = readParenLiteral(); | 
|  | OutputSection *Cmd = Script->getOrCreateOutputSection(Name); | 
|  | // Linker script does not create an output section if its content is empty. | 
|  | // We want to allow SIZEOF(.foo) where .foo is a section which happened to | 
|  | // be empty. | 
|  | return [=] { return Cmd->Size; }; | 
|  | } | 
|  | if (Tok == "SIZEOF_HEADERS") | 
|  | return [=] { return elf::getHeaderSize(); }; | 
|  |  | 
|  | // Tok is the dot. | 
|  | if (Tok == ".") | 
|  | return [=] { return Script->getSymbolValue(Tok, Location); }; | 
|  |  | 
|  | // Tok is a literal number. | 
|  | if (Optional<uint64_t> Val = parseInt(Tok)) | 
|  | return [=] { return *Val; }; | 
|  |  | 
|  | // Tok is a symbol name. | 
|  | if (!isValidCIdentifier(Tok)) | 
|  | setError("malformed number: " + Tok); | 
|  | Script->ReferencedSymbols.push_back(Tok); | 
|  | return [=] { return Script->getSymbolValue(Tok, Location); }; | 
|  | } | 
|  |  | 
|  | Expr ScriptParser::readTernary(Expr Cond) { | 
|  | Expr L = readExpr(); | 
|  | expect(":"); | 
|  | Expr R = readExpr(); | 
|  | return [=] { return Cond().getValue() ? L() : R(); }; | 
|  | } | 
|  |  | 
|  | Expr ScriptParser::readParenExpr() { | 
|  | expect("("); | 
|  | Expr E = readExpr(); | 
|  | expect(")"); | 
|  | return E; | 
|  | } | 
|  |  | 
|  | std::vector<StringRef> ScriptParser::readOutputSectionPhdrs() { | 
|  | std::vector<StringRef> Phdrs; | 
|  | while (!errorCount() && peek().startswith(":")) { | 
|  | StringRef Tok = next(); | 
|  | Phdrs.push_back((Tok.size() == 1) ? next() : Tok.substr(1)); | 
|  | } | 
|  | return Phdrs; | 
|  | } | 
|  |  | 
|  | // Read a program header type name. The next token must be a | 
|  | // name of a program header type or a constant (e.g. "0x3"). | 
|  | unsigned ScriptParser::readPhdrType() { | 
|  | StringRef Tok = next(); | 
|  | if (Optional<uint64_t> Val = parseInt(Tok)) | 
|  | return *Val; | 
|  |  | 
|  | unsigned Ret = StringSwitch<unsigned>(Tok) | 
|  | .Case("PT_NULL", PT_NULL) | 
|  | .Case("PT_LOAD", PT_LOAD) | 
|  | .Case("PT_DYNAMIC", PT_DYNAMIC) | 
|  | .Case("PT_INTERP", PT_INTERP) | 
|  | .Case("PT_NOTE", PT_NOTE) | 
|  | .Case("PT_SHLIB", PT_SHLIB) | 
|  | .Case("PT_PHDR", PT_PHDR) | 
|  | .Case("PT_TLS", PT_TLS) | 
|  | .Case("PT_GNU_EH_FRAME", PT_GNU_EH_FRAME) | 
|  | .Case("PT_GNU_STACK", PT_GNU_STACK) | 
|  | .Case("PT_GNU_RELRO", PT_GNU_RELRO) | 
|  | .Case("PT_OPENBSD_RANDOMIZE", PT_OPENBSD_RANDOMIZE) | 
|  | .Case("PT_OPENBSD_WXNEEDED", PT_OPENBSD_WXNEEDED) | 
|  | .Case("PT_OPENBSD_BOOTDATA", PT_OPENBSD_BOOTDATA) | 
|  | .Default(-1); | 
|  |  | 
|  | if (Ret == (unsigned)-1) { | 
|  | setError("invalid program header type: " + Tok); | 
|  | return PT_NULL; | 
|  | } | 
|  | return Ret; | 
|  | } | 
|  |  | 
|  | // Reads an anonymous version declaration. | 
|  | void ScriptParser::readAnonymousDeclaration() { | 
|  | std::vector<SymbolVersion> Locals; | 
|  | std::vector<SymbolVersion> Globals; | 
|  | std::tie(Locals, Globals) = readSymbols(); | 
|  |  | 
|  | for (SymbolVersion V : Locals) { | 
|  | if (V.Name == "*") | 
|  | Config->DefaultSymbolVersion = VER_NDX_LOCAL; | 
|  | else | 
|  | Config->VersionScriptLocals.push_back(V); | 
|  | } | 
|  |  | 
|  | for (SymbolVersion V : Globals) | 
|  | Config->VersionScriptGlobals.push_back(V); | 
|  |  | 
|  | expect(";"); | 
|  | } | 
|  |  | 
|  | // Reads a non-anonymous version definition, | 
|  | // e.g. "VerStr { global: foo; bar; local: *; };". | 
|  | void ScriptParser::readVersionDeclaration(StringRef VerStr) { | 
|  | // Read a symbol list. | 
|  | std::vector<SymbolVersion> Locals; | 
|  | std::vector<SymbolVersion> Globals; | 
|  | std::tie(Locals, Globals) = readSymbols(); | 
|  |  | 
|  | for (SymbolVersion V : Locals) { | 
|  | if (V.Name == "*") | 
|  | Config->DefaultSymbolVersion = VER_NDX_LOCAL; | 
|  | else | 
|  | Config->VersionScriptLocals.push_back(V); | 
|  | } | 
|  |  | 
|  | // Create a new version definition and add that to the global symbols. | 
|  | VersionDefinition Ver; | 
|  | Ver.Name = VerStr; | 
|  | Ver.Globals = Globals; | 
|  |  | 
|  | // User-defined version number starts from 2 because 0 and 1 are | 
|  | // reserved for VER_NDX_LOCAL and VER_NDX_GLOBAL, respectively. | 
|  | Ver.Id = Config->VersionDefinitions.size() + 2; | 
|  | Config->VersionDefinitions.push_back(Ver); | 
|  |  | 
|  | // Each version may have a parent version. For example, "Ver2" | 
|  | // defined as "Ver2 { global: foo; local: *; } Ver1;" has "Ver1" | 
|  | // as a parent. This version hierarchy is, probably against your | 
|  | // instinct, purely for hint; the runtime doesn't care about it | 
|  | // at all. In LLD, we simply ignore it. | 
|  | if (peek() != ";") | 
|  | skip(); | 
|  | expect(";"); | 
|  | } | 
|  |  | 
|  | static bool hasWildcard(StringRef S) { | 
|  | return S.find_first_of("?*[") != StringRef::npos; | 
|  | } | 
|  |  | 
|  | // Reads a list of symbols, e.g. "{ global: foo; bar; local: *; };". | 
|  | std::pair<std::vector<SymbolVersion>, std::vector<SymbolVersion>> | 
|  | ScriptParser::readSymbols() { | 
|  | std::vector<SymbolVersion> Locals; | 
|  | std::vector<SymbolVersion> Globals; | 
|  | std::vector<SymbolVersion> *V = &Globals; | 
|  |  | 
|  | while (!errorCount()) { | 
|  | if (consume("}")) | 
|  | break; | 
|  | if (consumeLabel("local")) { | 
|  | V = &Locals; | 
|  | continue; | 
|  | } | 
|  | if (consumeLabel("global")) { | 
|  | V = &Globals; | 
|  | continue; | 
|  | } | 
|  |  | 
|  | if (consume("extern")) { | 
|  | std::vector<SymbolVersion> Ext = readVersionExtern(); | 
|  | V->insert(V->end(), Ext.begin(), Ext.end()); | 
|  | } else { | 
|  | StringRef Tok = next(); | 
|  | V->push_back({unquote(Tok), false, hasWildcard(Tok)}); | 
|  | } | 
|  | expect(";"); | 
|  | } | 
|  | return {Locals, Globals}; | 
|  | } | 
|  |  | 
|  | // Reads an "extern C++" directive, e.g., | 
|  | // "extern "C++" { ns::*; "f(int, double)"; };" | 
|  | // | 
|  | // The last semicolon is optional. E.g. this is OK: | 
|  | // "extern "C++" { ns::*; "f(int, double)" };" | 
|  | std::vector<SymbolVersion> ScriptParser::readVersionExtern() { | 
|  | StringRef Tok = next(); | 
|  | bool IsCXX = Tok == "\"C++\""; | 
|  | if (!IsCXX && Tok != "\"C\"") | 
|  | setError("Unknown language"); | 
|  | expect("{"); | 
|  |  | 
|  | std::vector<SymbolVersion> Ret; | 
|  | while (!errorCount() && peek() != "}") { | 
|  | StringRef Tok = next(); | 
|  | bool HasWildcard = !Tok.startswith("\"") && hasWildcard(Tok); | 
|  | Ret.push_back({unquote(Tok), IsCXX, HasWildcard}); | 
|  | if (consume("}")) | 
|  | return Ret; | 
|  | expect(";"); | 
|  | } | 
|  |  | 
|  | expect("}"); | 
|  | return Ret; | 
|  | } | 
|  |  | 
|  | uint64_t ScriptParser::readMemoryAssignment(StringRef S1, StringRef S2, | 
|  | StringRef S3) { | 
|  | if (!consume(S1) && !consume(S2) && !consume(S3)) { | 
|  | setError("expected one of: " + S1 + ", " + S2 + ", or " + S3); | 
|  | return 0; | 
|  | } | 
|  | expect("="); | 
|  | return readExpr()().getValue(); | 
|  | } | 
|  |  | 
|  | // Parse the MEMORY command as specified in: | 
|  | // https://sourceware.org/binutils/docs/ld/MEMORY.html | 
|  | // | 
|  | // MEMORY { name [(attr)] : ORIGIN = origin, LENGTH = len ... } | 
|  | void ScriptParser::readMemory() { | 
|  | expect("{"); | 
|  | while (!errorCount() && !consume("}")) { | 
|  | StringRef Tok = next(); | 
|  | if (Tok == "INCLUDE") { | 
|  | readInclude(); | 
|  | continue; | 
|  | } | 
|  |  | 
|  | uint32_t Flags = 0; | 
|  | uint32_t NegFlags = 0; | 
|  | if (consume("(")) { | 
|  | std::tie(Flags, NegFlags) = readMemoryAttributes(); | 
|  | expect(")"); | 
|  | } | 
|  | expect(":"); | 
|  |  | 
|  | uint64_t Origin = readMemoryAssignment("ORIGIN", "org", "o"); | 
|  | expect(","); | 
|  | uint64_t Length = readMemoryAssignment("LENGTH", "len", "l"); | 
|  |  | 
|  | // Add the memory region to the region map. | 
|  | MemoryRegion *MR = make<MemoryRegion>(Tok, Origin, Length, Flags, NegFlags); | 
|  | if (!Script->MemoryRegions.insert({Tok, MR}).second) | 
|  | setError("region '" + Tok + "' already defined"); | 
|  | } | 
|  | } | 
|  |  | 
|  | // This function parses the attributes used to match against section | 
|  | // flags when placing output sections in a memory region. These flags | 
|  | // are only used when an explicit memory region name is not used. | 
|  | std::pair<uint32_t, uint32_t> ScriptParser::readMemoryAttributes() { | 
|  | uint32_t Flags = 0; | 
|  | uint32_t NegFlags = 0; | 
|  | bool Invert = false; | 
|  |  | 
|  | for (char C : next().lower()) { | 
|  | uint32_t Flag = 0; | 
|  | if (C == '!') | 
|  | Invert = !Invert; | 
|  | else if (C == 'w') | 
|  | Flag = SHF_WRITE; | 
|  | else if (C == 'x') | 
|  | Flag = SHF_EXECINSTR; | 
|  | else if (C == 'a') | 
|  | Flag = SHF_ALLOC; | 
|  | else if (C != 'r') | 
|  | setError("invalid memory region attribute"); | 
|  |  | 
|  | if (Invert) | 
|  | NegFlags |= Flag; | 
|  | else | 
|  | Flags |= Flag; | 
|  | } | 
|  | return {Flags, NegFlags}; | 
|  | } | 
|  |  | 
|  | void elf::readLinkerScript(MemoryBufferRef MB) { | 
|  | ScriptParser(MB).readLinkerScript(); | 
|  | } | 
|  |  | 
|  | void elf::readVersionScript(MemoryBufferRef MB) { | 
|  | ScriptParser(MB).readVersionScript(); | 
|  | } | 
|  |  | 
|  | void elf::readDynamicList(MemoryBufferRef MB) { | 
|  | ScriptParser(MB).readDynamicList(); | 
|  | } | 
|  |  | 
|  | void elf::readDefsym(StringRef Name, MemoryBufferRef MB) { | 
|  | ScriptParser(MB).readDefsym(Name); | 
|  | } |