1f7c5fbb1SRui Ueyama //===- LinkerScript.cpp ---------------------------------------------------===// 2f7c5fbb1SRui Ueyama // 3f7c5fbb1SRui Ueyama // The LLVM Linker 4f7c5fbb1SRui Ueyama // 5f7c5fbb1SRui Ueyama // This file is distributed under the University of Illinois Open Source 6f7c5fbb1SRui Ueyama // License. See LICENSE.TXT for details. 7f7c5fbb1SRui Ueyama // 8f7c5fbb1SRui Ueyama //===----------------------------------------------------------------------===// 9f7c5fbb1SRui Ueyama // 10f7c5fbb1SRui Ueyama // This file contains the parser/evaluator of the linker script. 11f7c5fbb1SRui Ueyama // It does not construct an AST but consume linker script directives directly. 1234f29246SRui Ueyama // Results are written to Driver or Config object. 13f7c5fbb1SRui Ueyama // 14f7c5fbb1SRui Ueyama //===----------------------------------------------------------------------===// 15f7c5fbb1SRui Ueyama 16717677afSRui Ueyama #include "LinkerScript.h" 17f7c5fbb1SRui Ueyama #include "Config.h" 18f7c5fbb1SRui Ueyama #include "Driver.h" 191ebc8ed7SRui Ueyama #include "InputSection.h" 20652852c5SGeorge Rimar #include "OutputSections.h" 21e77b5bf6SAdhemerval Zanella #include "ScriptParser.h" 22f7c5fbb1SRui Ueyama #include "SymbolTable.h" 23960504b9SRui Ueyama #include "llvm/ADT/StringSwitch.h" 24652852c5SGeorge Rimar #include "llvm/Support/ELF.h" 25f7c5fbb1SRui Ueyama #include "llvm/Support/FileSystem.h" 26f7c5fbb1SRui Ueyama #include "llvm/Support/MemoryBuffer.h" 27f03f3cc1SRui Ueyama #include "llvm/Support/Path.h" 28a47ee68dSRui Ueyama #include "llvm/Support/StringSaver.h" 29f7c5fbb1SRui Ueyama 30f7c5fbb1SRui Ueyama using namespace llvm; 31652852c5SGeorge Rimar using namespace llvm::ELF; 321ebc8ed7SRui Ueyama using namespace llvm::object; 33f7c5fbb1SRui Ueyama using namespace lld; 34e0df00b9SRafael Espindola using namespace lld::elf; 35f7c5fbb1SRui Ueyama 36e0df00b9SRafael Espindola LinkerScript *elf::Script; 37717677afSRui Ueyama 38652852c5SGeorge Rimar static uint64_t getInteger(StringRef S) { 39652852c5SGeorge Rimar uint64_t V; 40652852c5SGeorge Rimar if (S.getAsInteger(0, V)) { 41652852c5SGeorge Rimar error("malformed number: " + S); 42652852c5SGeorge Rimar return 0; 43652852c5SGeorge Rimar } 44652852c5SGeorge Rimar return V; 45652852c5SGeorge Rimar } 46652852c5SGeorge Rimar 47960504b9SRui Ueyama static int precedence(StringRef Op) { 48960504b9SRui Ueyama return StringSwitch<int>(Op) 49960504b9SRui Ueyama .Case("*", 4) 50960504b9SRui Ueyama .Case("/", 3) 51960504b9SRui Ueyama .Case("+", 2) 52960504b9SRui Ueyama .Case("-", 2) 53960504b9SRui Ueyama .Case("&", 1) 54960504b9SRui Ueyama .Default(-1); 55960504b9SRui Ueyama } 56960504b9SRui Ueyama 57960504b9SRui Ueyama static StringRef next(ArrayRef<StringRef> &Tokens) { 58960504b9SRui Ueyama if (Tokens.empty()) { 59960504b9SRui Ueyama error("no next token"); 60960504b9SRui Ueyama return ""; 61960504b9SRui Ueyama } 62960504b9SRui Ueyama StringRef Tok = Tokens.front(); 63960504b9SRui Ueyama Tokens = Tokens.slice(1); 64960504b9SRui Ueyama return Tok; 65960504b9SRui Ueyama } 66960504b9SRui Ueyama 67960504b9SRui Ueyama static uint64_t parseExpr(uint64_t Lhs, int MinPrec, 68960504b9SRui Ueyama ArrayRef<StringRef> &Tokens, uint64_t Dot); 69960504b9SRui Ueyama 70960504b9SRui Ueyama // This is a part of the operator-precedence parser to evaluate 71960504b9SRui Ueyama // arithmetic expressions in SECTIONS command. This function evaluates an 72960504b9SRui Ueyama // integer literal, a parenthesized expression or the special variable ".". 73960504b9SRui Ueyama static uint64_t parsePrimary(ArrayRef<StringRef> &Tokens, uint64_t Dot) { 74960504b9SRui Ueyama StringRef Tok = next(Tokens); 75960504b9SRui Ueyama if (Tok == ".") 76960504b9SRui Ueyama return Dot; 77960504b9SRui Ueyama if (Tok == "(") { 78960504b9SRui Ueyama uint64_t V = parsePrimary(Tokens, Dot); 79960504b9SRui Ueyama V = parseExpr(V, 0, Tokens, Dot); 80960504b9SRui Ueyama if (Tokens.empty()) { 81960504b9SRui Ueyama error(") expected"); 82960504b9SRui Ueyama } else { 83960504b9SRui Ueyama Tok = next(Tokens); 84960504b9SRui Ueyama if (Tok != ")") 85960504b9SRui Ueyama error(") expected, but got " + Tok); 86960504b9SRui Ueyama } 87960504b9SRui Ueyama return V; 88960504b9SRui Ueyama } 89960504b9SRui Ueyama return getInteger(Tok); 90960504b9SRui Ueyama } 91960504b9SRui Ueyama 92960504b9SRui Ueyama static uint64_t apply(StringRef Op, uint64_t L, uint64_t R) { 93960504b9SRui Ueyama if (Op == "+") 94960504b9SRui Ueyama return L + R; 95960504b9SRui Ueyama if (Op == "-") 96960504b9SRui Ueyama return L - R; 97960504b9SRui Ueyama if (Op == "*") 98960504b9SRui Ueyama return L * R; 99960504b9SRui Ueyama if (Op == "/") { 100960504b9SRui Ueyama if (R == 0) { 101960504b9SRui Ueyama error("division by zero"); 102960504b9SRui Ueyama return 0; 103960504b9SRui Ueyama } 104960504b9SRui Ueyama return L / R; 105960504b9SRui Ueyama } 106960504b9SRui Ueyama if (Op == "&") 107960504b9SRui Ueyama return L & R; 1087a81d674SRui Ueyama llvm_unreachable("invalid operator"); 109652852c5SGeorge Rimar return 0; 110652852c5SGeorge Rimar } 111652852c5SGeorge Rimar 112960504b9SRui Ueyama // This is an operator-precedence parser to evaluate 113960504b9SRui Ueyama // arithmetic expressions in SECTIONS command. 114960504b9SRui Ueyama static uint64_t parseExpr(uint64_t Lhs, int MinPrec, 115960504b9SRui Ueyama ArrayRef<StringRef> &Tokens, uint64_t Dot) { 116960504b9SRui Ueyama while (!Tokens.empty()) { 117960504b9SRui Ueyama // Read an operator and an expression. 118960504b9SRui Ueyama StringRef Op1 = Tokens.front(); 119960504b9SRui Ueyama if (precedence(Op1) < MinPrec) 120960504b9SRui Ueyama return Lhs; 121960504b9SRui Ueyama next(Tokens); 122960504b9SRui Ueyama uint64_t Rhs = parsePrimary(Tokens, Dot); 123960504b9SRui Ueyama 124960504b9SRui Ueyama // Evaluate the remaining part of the expression first if the 125960504b9SRui Ueyama // next operator has greater precedence than the previous one. 126960504b9SRui Ueyama // For example, if we have read "+" and "3", and if the next 127960504b9SRui Ueyama // operator is "*", then we'll evaluate 3 * ... part first. 128960504b9SRui Ueyama while (!Tokens.empty()) { 129960504b9SRui Ueyama StringRef Op2 = Tokens.front(); 130960504b9SRui Ueyama if (precedence(Op2) <= precedence(Op1)) 131960504b9SRui Ueyama break; 132960504b9SRui Ueyama Rhs = parseExpr(Rhs, precedence(Op2), Tokens, Dot); 133652852c5SGeorge Rimar } 134960504b9SRui Ueyama 135960504b9SRui Ueyama Lhs = apply(Op1, Lhs, Rhs); 136960504b9SRui Ueyama } 137960504b9SRui Ueyama return Lhs; 138960504b9SRui Ueyama } 139960504b9SRui Ueyama 140960504b9SRui Ueyama // Evaluates the expression given by list of tokens. 141*0536ec02SRui Ueyama static uint64_t evaluate(ArrayRef<StringRef> Tokens, uint64_t Dot) { 142960504b9SRui Ueyama uint64_t V = parsePrimary(Tokens, Dot); 143960504b9SRui Ueyama V = parseExpr(V, 0, Tokens, Dot); 144960504b9SRui Ueyama if (!Tokens.empty()) 145960504b9SRui Ueyama error("stray token: " + Tokens[0]); 146960504b9SRui Ueyama return V; 147652852c5SGeorge Rimar } 148652852c5SGeorge Rimar 1491ebc8ed7SRui Ueyama template <class ELFT> 150481c2ce6SGeorge Rimar SectionRule *LinkerScript::find(InputSectionBase<ELFT> *S) { 1511ebc8ed7SRui Ueyama for (SectionRule &R : Sections) 1521ebc8ed7SRui Ueyama if (R.match(S)) 153481c2ce6SGeorge Rimar return &R; 154481c2ce6SGeorge Rimar return nullptr; 155481c2ce6SGeorge Rimar } 156481c2ce6SGeorge Rimar 157481c2ce6SGeorge Rimar template <class ELFT> 158481c2ce6SGeorge Rimar StringRef LinkerScript::getOutputSection(InputSectionBase<ELFT> *S) { 159481c2ce6SGeorge Rimar SectionRule *R = find(S); 160481c2ce6SGeorge Rimar return R ? R->Dest : ""; 161717677afSRui Ueyama } 162717677afSRui Ueyama 1631ebc8ed7SRui Ueyama template <class ELFT> 1641ebc8ed7SRui Ueyama bool LinkerScript::isDiscarded(InputSectionBase<ELFT> *S) { 1651ebc8ed7SRui Ueyama return getOutputSection(S) == "/DISCARD/"; 166717677afSRui Ueyama } 167717677afSRui Ueyama 168481c2ce6SGeorge Rimar template <class ELFT> bool LinkerScript::shouldKeep(InputSectionBase<ELFT> *S) { 169481c2ce6SGeorge Rimar SectionRule *R = find(S); 170481c2ce6SGeorge Rimar return R && R->Keep; 171481c2ce6SGeorge Rimar } 172481c2ce6SGeorge Rimar 173652852c5SGeorge Rimar template <class ELFT> 1747c18c28cSRui Ueyama static OutputSectionBase<ELFT> * 1757c18c28cSRui Ueyama findSection(std::vector<OutputSectionBase<ELFT> *> &V, StringRef Name) { 1767c18c28cSRui Ueyama for (OutputSectionBase<ELFT> *Sec : V) 1777c18c28cSRui Ueyama if (Sec->getName() == Name) 1787c18c28cSRui Ueyama return Sec; 1797c18c28cSRui Ueyama return nullptr; 1807c18c28cSRui Ueyama } 1817c18c28cSRui Ueyama 1827c18c28cSRui Ueyama template <class ELFT> 1837c18c28cSRui Ueyama void LinkerScript::assignAddresses( 1847c18c28cSRui Ueyama std::vector<OutputSectionBase<ELFT> *> &Sections) { 1857c18c28cSRui Ueyama typedef typename ELFT::uint uintX_t; 1867c18c28cSRui Ueyama 187652852c5SGeorge Rimar // Orphan sections are sections present in the input files which 1887c18c28cSRui Ueyama // are not explicitly placed into the output file by the linker script. 1897c18c28cSRui Ueyama // We place orphan sections at end of file. 1907c18c28cSRui Ueyama // Other linkers places them using some heuristics as described in 191652852c5SGeorge Rimar // https://sourceware.org/binutils/docs/ld/Orphan-Sections.html#Orphan-Sections. 1927c18c28cSRui Ueyama for (OutputSectionBase<ELFT> *Sec : Sections) { 193652852c5SGeorge Rimar StringRef Name = Sec->getName(); 194652852c5SGeorge Rimar auto I = std::find(SectionOrder.begin(), SectionOrder.end(), Name); 195652852c5SGeorge Rimar if (I == SectionOrder.end()) 1969e957a0aSRui Ueyama Commands.push_back({SectionKind, {}, Name}); 197652852c5SGeorge Rimar } 198652852c5SGeorge Rimar 1997c18c28cSRui Ueyama // Assign addresses as instructed by linker script SECTIONS sub-commands. 200652852c5SGeorge Rimar uintX_t ThreadBssOffset = 0; 201652852c5SGeorge Rimar uintX_t VA = 202652852c5SGeorge Rimar Out<ELFT>::ElfHeader->getSize() + Out<ELFT>::ProgramHeaders->getSize(); 203652852c5SGeorge Rimar 2049e957a0aSRui Ueyama for (SectionsCommand &Cmd : Commands) { 2059e957a0aSRui Ueyama if (Cmd.Kind == ExprKind) { 2069e957a0aSRui Ueyama VA = evaluate(Cmd.Expr, VA); 207652852c5SGeorge Rimar continue; 208652852c5SGeorge Rimar } 209652852c5SGeorge Rimar 2109e957a0aSRui Ueyama OutputSectionBase<ELFT> *Sec = findSection(Sections, Cmd.SectionName); 2117c18c28cSRui Ueyama if (!Sec) 212652852c5SGeorge Rimar continue; 213652852c5SGeorge Rimar 214652852c5SGeorge Rimar if ((Sec->getFlags() & SHF_TLS) && Sec->getType() == SHT_NOBITS) { 215652852c5SGeorge Rimar uintX_t TVA = VA + ThreadBssOffset; 2167c18c28cSRui Ueyama TVA = alignTo(TVA, Sec->getAlign()); 217652852c5SGeorge Rimar Sec->setVA(TVA); 218652852c5SGeorge Rimar ThreadBssOffset = TVA - VA + Sec->getSize(); 219652852c5SGeorge Rimar continue; 220652852c5SGeorge Rimar } 221652852c5SGeorge Rimar 222652852c5SGeorge Rimar if (Sec->getFlags() & SHF_ALLOC) { 2237c18c28cSRui Ueyama VA = alignTo(VA, Sec->getAlign()); 224652852c5SGeorge Rimar Sec->setVA(VA); 225652852c5SGeorge Rimar VA += Sec->getSize(); 226652852c5SGeorge Rimar continue; 227652852c5SGeorge Rimar } 228652852c5SGeorge Rimar } 229652852c5SGeorge Rimar } 230652852c5SGeorge Rimar 231e2ee72b5SGeorge Rimar ArrayRef<uint8_t> LinkerScript::getFiller(StringRef Name) { 2323e808976SRui Ueyama auto I = Filler.find(Name); 2333e808976SRui Ueyama if (I == Filler.end()) 234e2ee72b5SGeorge Rimar return {}; 2353e808976SRui Ueyama return I->second; 236e2ee72b5SGeorge Rimar } 237e2ee72b5SGeorge Rimar 238e9c58065SRui Ueyama // A compartor to sort output sections. Returns -1 or 1 if both 239e9c58065SRui Ueyama // A and B are mentioned in linker scripts. Otherwise, returns 0 240e9c58065SRui Ueyama // to use the default rule which is implemented in Writer.cpp. 241717677afSRui Ueyama int LinkerScript::compareSections(StringRef A, StringRef B) { 2423e808976SRui Ueyama auto E = SectionOrder.end(); 2433e808976SRui Ueyama auto I = std::find(SectionOrder.begin(), E, A); 2443e808976SRui Ueyama auto J = std::find(SectionOrder.begin(), E, B); 2453e808976SRui Ueyama if (I == E || J == E) 246717677afSRui Ueyama return 0; 247717677afSRui Ueyama return I < J ? -1 : 1; 248717677afSRui Ueyama } 249717677afSRui Ueyama 250cb2aeb66SGeorge Rimar // Returns true if S matches T. S can contain glob meta-characters. 251cb2aeb66SGeorge Rimar // The asterisk ('*') matches zero or more characacters, and the question 252cb2aeb66SGeorge Rimar // mark ('?') matches one character. 2531ebc8ed7SRui Ueyama static bool matchStr(StringRef S, StringRef T) { 2541ebc8ed7SRui Ueyama for (;;) { 2551ebc8ed7SRui Ueyama if (S.empty()) 2561ebc8ed7SRui Ueyama return T.empty(); 2571ebc8ed7SRui Ueyama if (S[0] == '*') { 2581ebc8ed7SRui Ueyama S = S.substr(1); 2591ebc8ed7SRui Ueyama if (S.empty()) 2601ebc8ed7SRui Ueyama // Fast path. If a pattern is '*', it matches anything. 2611ebc8ed7SRui Ueyama return true; 2621ebc8ed7SRui Ueyama for (size_t I = 0, E = T.size(); I < E; ++I) 2631ebc8ed7SRui Ueyama if (matchStr(S, T.substr(I))) 2641ebc8ed7SRui Ueyama return true; 2651ebc8ed7SRui Ueyama return false; 2661ebc8ed7SRui Ueyama } 267cb2aeb66SGeorge Rimar if (T.empty() || (S[0] != T[0] && S[0] != '?')) 2681ebc8ed7SRui Ueyama return false; 2691ebc8ed7SRui Ueyama S = S.substr(1); 2701ebc8ed7SRui Ueyama T = T.substr(1); 2711ebc8ed7SRui Ueyama } 2721ebc8ed7SRui Ueyama } 2731ebc8ed7SRui Ueyama 2741ebc8ed7SRui Ueyama template <class ELFT> bool SectionRule::match(InputSectionBase<ELFT> *S) { 2751ebc8ed7SRui Ueyama return matchStr(SectionPattern, S->getSectionName()); 2761ebc8ed7SRui Ueyama } 2771ebc8ed7SRui Ueyama 278e77b5bf6SAdhemerval Zanella class elf::ScriptParser final : public elf::ScriptParserBase { 279c3794e58SGeorge Rimar typedef void (ScriptParser::*Handler)(); 280c3794e58SGeorge Rimar 281f7c5fbb1SRui Ueyama public: 282717677afSRui Ueyama ScriptParser(BumpPtrAllocator *A, StringRef S, bool B) 283e77b5bf6SAdhemerval Zanella : ScriptParserBase(S), Saver(*A), IsUnderSysroot(B) {} 284f23b2320SGeorge Rimar 285e77b5bf6SAdhemerval Zanella void run() override; 286f7c5fbb1SRui Ueyama 287f7c5fbb1SRui Ueyama private: 28852a1509eSRui Ueyama void addFile(StringRef Path); 28952a1509eSRui Ueyama 290f7c5fbb1SRui Ueyama void readAsNeeded(); 29190c5099eSDenis Protivensky void readEntry(); 29283f406cfSGeorge Rimar void readExtern(); 293f7c5fbb1SRui Ueyama void readGroup(); 29431aa1f83SRui Ueyama void readInclude(); 295c3794e58SGeorge Rimar void readNothing() {} 296ee59282bSRui Ueyama void readOutput(); 2979159ce93SDavide Italiano void readOutputArch(); 298f7c5fbb1SRui Ueyama void readOutputFormat(); 29968a39a65SDavide Italiano void readSearchDir(); 3008e3b38abSDenis Protivensky void readSections(); 3018e3b38abSDenis Protivensky 302652852c5SGeorge Rimar void readLocationCounterValue(); 3038e3b38abSDenis Protivensky void readOutputSectionDescription(); 304481c2ce6SGeorge Rimar void readSectionPatterns(StringRef OutSec, bool Keep); 305f7c5fbb1SRui Ueyama 306a47ee68dSRui Ueyama StringSaver Saver; 307c3794e58SGeorge Rimar const static StringMap<Handler> Cmd; 30816b0cc9eSSimon Atanasyan bool IsUnderSysroot; 309f7c5fbb1SRui Ueyama }; 310f7c5fbb1SRui Ueyama 311e0df00b9SRafael Espindola const StringMap<elf::ScriptParser::Handler> elf::ScriptParser::Cmd = { 312c3794e58SGeorge Rimar {"ENTRY", &ScriptParser::readEntry}, 313c3794e58SGeorge Rimar {"EXTERN", &ScriptParser::readExtern}, 314c3794e58SGeorge Rimar {"GROUP", &ScriptParser::readGroup}, 315c3794e58SGeorge Rimar {"INCLUDE", &ScriptParser::readInclude}, 316c3794e58SGeorge Rimar {"INPUT", &ScriptParser::readGroup}, 317c3794e58SGeorge Rimar {"OUTPUT", &ScriptParser::readOutput}, 318c3794e58SGeorge Rimar {"OUTPUT_ARCH", &ScriptParser::readOutputArch}, 319c3794e58SGeorge Rimar {"OUTPUT_FORMAT", &ScriptParser::readOutputFormat}, 320c3794e58SGeorge Rimar {"SEARCH_DIR", &ScriptParser::readSearchDir}, 321c3794e58SGeorge Rimar {"SECTIONS", &ScriptParser::readSections}, 322c3794e58SGeorge Rimar {";", &ScriptParser::readNothing}}; 323c3794e58SGeorge Rimar 324717677afSRui Ueyama void ScriptParser::run() { 325f7c5fbb1SRui Ueyama while (!atEOF()) { 326f7c5fbb1SRui Ueyama StringRef Tok = next(); 327c3794e58SGeorge Rimar if (Handler Fn = Cmd.lookup(Tok)) 328c3794e58SGeorge Rimar (this->*Fn)(); 329c3794e58SGeorge Rimar else 3305761042dSGeorge Rimar setError("unknown directive: " + Tok); 331f7c5fbb1SRui Ueyama } 332f7c5fbb1SRui Ueyama } 333f7c5fbb1SRui Ueyama 334717677afSRui Ueyama void ScriptParser::addFile(StringRef S) { 33516b0cc9eSSimon Atanasyan if (IsUnderSysroot && S.startswith("/")) { 33616b0cc9eSSimon Atanasyan SmallString<128> Path; 33716b0cc9eSSimon Atanasyan (Config->Sysroot + S).toStringRef(Path); 33816b0cc9eSSimon Atanasyan if (sys::fs::exists(Path)) { 33916b0cc9eSSimon Atanasyan Driver->addFile(Saver.save(Path.str())); 34016b0cc9eSSimon Atanasyan return; 34116b0cc9eSSimon Atanasyan } 34216b0cc9eSSimon Atanasyan } 34316b0cc9eSSimon Atanasyan 344f03f3cc1SRui Ueyama if (sys::path::is_absolute(S)) { 34552a1509eSRui Ueyama Driver->addFile(S); 34652a1509eSRui Ueyama } else if (S.startswith("=")) { 34752a1509eSRui Ueyama if (Config->Sysroot.empty()) 34852a1509eSRui Ueyama Driver->addFile(S.substr(1)); 34952a1509eSRui Ueyama else 35052a1509eSRui Ueyama Driver->addFile(Saver.save(Config->Sysroot + "/" + S.substr(1))); 35152a1509eSRui Ueyama } else if (S.startswith("-l")) { 35221eecb4fSRui Ueyama Driver->addLibrary(S.substr(2)); 353a1b8fc3bSSimon Atanasyan } else if (sys::fs::exists(S)) { 354a1b8fc3bSSimon Atanasyan Driver->addFile(S); 35552a1509eSRui Ueyama } else { 35652a1509eSRui Ueyama std::string Path = findFromSearchPaths(S); 35752a1509eSRui Ueyama if (Path.empty()) 358777f9630SGeorge Rimar setError("unable to find " + S); 359025d59b1SRui Ueyama else 36052a1509eSRui Ueyama Driver->addFile(Saver.save(Path)); 36152a1509eSRui Ueyama } 36252a1509eSRui Ueyama } 36352a1509eSRui Ueyama 364717677afSRui Ueyama void ScriptParser::readAsNeeded() { 365f7c5fbb1SRui Ueyama expect("("); 36635da9b6eSRui Ueyama bool Orig = Config->AsNeeded; 36735da9b6eSRui Ueyama Config->AsNeeded = true; 368025d59b1SRui Ueyama while (!Error) { 369f7c5fbb1SRui Ueyama StringRef Tok = next(); 370f7c5fbb1SRui Ueyama if (Tok == ")") 37135da9b6eSRui Ueyama break; 37252a1509eSRui Ueyama addFile(Tok); 373f7c5fbb1SRui Ueyama } 37435da9b6eSRui Ueyama Config->AsNeeded = Orig; 375f7c5fbb1SRui Ueyama } 376f7c5fbb1SRui Ueyama 377717677afSRui Ueyama void ScriptParser::readEntry() { 37890c5099eSDenis Protivensky // -e <symbol> takes predecence over ENTRY(<symbol>). 37990c5099eSDenis Protivensky expect("("); 38090c5099eSDenis Protivensky StringRef Tok = next(); 38190c5099eSDenis Protivensky if (Config->Entry.empty()) 38290c5099eSDenis Protivensky Config->Entry = Tok; 38390c5099eSDenis Protivensky expect(")"); 38490c5099eSDenis Protivensky } 38590c5099eSDenis Protivensky 386717677afSRui Ueyama void ScriptParser::readExtern() { 38783f406cfSGeorge Rimar expect("("); 388025d59b1SRui Ueyama while (!Error) { 38983f406cfSGeorge Rimar StringRef Tok = next(); 39083f406cfSGeorge Rimar if (Tok == ")") 39183f406cfSGeorge Rimar return; 39283f406cfSGeorge Rimar Config->Undefined.push_back(Tok); 39383f406cfSGeorge Rimar } 39483f406cfSGeorge Rimar } 39583f406cfSGeorge Rimar 396717677afSRui Ueyama void ScriptParser::readGroup() { 397f7c5fbb1SRui Ueyama expect("("); 398025d59b1SRui Ueyama while (!Error) { 399f7c5fbb1SRui Ueyama StringRef Tok = next(); 400f7c5fbb1SRui Ueyama if (Tok == ")") 401f7c5fbb1SRui Ueyama return; 402f7c5fbb1SRui Ueyama if (Tok == "AS_NEEDED") { 403f7c5fbb1SRui Ueyama readAsNeeded(); 404f7c5fbb1SRui Ueyama continue; 405f7c5fbb1SRui Ueyama } 40652a1509eSRui Ueyama addFile(Tok); 407f7c5fbb1SRui Ueyama } 408f7c5fbb1SRui Ueyama } 409f7c5fbb1SRui Ueyama 410717677afSRui Ueyama void ScriptParser::readInclude() { 41131aa1f83SRui Ueyama StringRef Tok = next(); 41231aa1f83SRui Ueyama auto MBOrErr = MemoryBuffer::getFile(Tok); 413025d59b1SRui Ueyama if (!MBOrErr) { 4145761042dSGeorge Rimar setError("cannot open " + Tok); 415025d59b1SRui Ueyama return; 416025d59b1SRui Ueyama } 41731aa1f83SRui Ueyama std::unique_ptr<MemoryBuffer> &MB = *MBOrErr; 418a47ee68dSRui Ueyama StringRef S = Saver.save(MB->getMemBufferRef().getBuffer()); 419a47ee68dSRui Ueyama std::vector<StringRef> V = tokenize(S); 42031aa1f83SRui Ueyama Tokens.insert(Tokens.begin() + Pos, V.begin(), V.end()); 42131aa1f83SRui Ueyama } 42231aa1f83SRui Ueyama 423717677afSRui Ueyama void ScriptParser::readOutput() { 424ee59282bSRui Ueyama // -o <file> takes predecence over OUTPUT(<file>). 425ee59282bSRui Ueyama expect("("); 426ee59282bSRui Ueyama StringRef Tok = next(); 427ee59282bSRui Ueyama if (Config->OutputFile.empty()) 428ee59282bSRui Ueyama Config->OutputFile = Tok; 429ee59282bSRui Ueyama expect(")"); 430ee59282bSRui Ueyama } 431ee59282bSRui Ueyama 432717677afSRui Ueyama void ScriptParser::readOutputArch() { 4339159ce93SDavide Italiano // Error checking only for now. 4349159ce93SDavide Italiano expect("("); 4359159ce93SDavide Italiano next(); 4369159ce93SDavide Italiano expect(")"); 4379159ce93SDavide Italiano } 4389159ce93SDavide Italiano 439717677afSRui Ueyama void ScriptParser::readOutputFormat() { 440f7c5fbb1SRui Ueyama // Error checking only for now. 441f7c5fbb1SRui Ueyama expect("("); 442f7c5fbb1SRui Ueyama next(); 4436836c618SDavide Italiano StringRef Tok = next(); 4446836c618SDavide Italiano if (Tok == ")") 4456836c618SDavide Italiano return; 446025d59b1SRui Ueyama if (Tok != ",") { 4475761042dSGeorge Rimar setError("unexpected token: " + Tok); 448025d59b1SRui Ueyama return; 449025d59b1SRui Ueyama } 4506836c618SDavide Italiano next(); 4516836c618SDavide Italiano expect(","); 4526836c618SDavide Italiano next(); 453f7c5fbb1SRui Ueyama expect(")"); 454f7c5fbb1SRui Ueyama } 455f7c5fbb1SRui Ueyama 456717677afSRui Ueyama void ScriptParser::readSearchDir() { 45768a39a65SDavide Italiano expect("("); 45806501920SRafael Espindola Config->SearchPaths.push_back(next()); 45968a39a65SDavide Italiano expect(")"); 46068a39a65SDavide Italiano } 46168a39a65SDavide Italiano 462717677afSRui Ueyama void ScriptParser::readSections() { 463652852c5SGeorge Rimar Script->DoLayout = true; 4648e3b38abSDenis Protivensky expect("{"); 465652852c5SGeorge Rimar while (!Error && !skip("}")) { 466652852c5SGeorge Rimar StringRef Tok = peek(); 467652852c5SGeorge Rimar if (Tok == ".") 468652852c5SGeorge Rimar readLocationCounterValue(); 469652852c5SGeorge Rimar else 4708e3b38abSDenis Protivensky readOutputSectionDescription(); 4718e3b38abSDenis Protivensky } 472652852c5SGeorge Rimar } 4738e3b38abSDenis Protivensky 474481c2ce6SGeorge Rimar void ScriptParser::readSectionPatterns(StringRef OutSec, bool Keep) { 475481c2ce6SGeorge Rimar expect("("); 476481c2ce6SGeorge Rimar while (!Error && !skip(")")) 477481c2ce6SGeorge Rimar Script->Sections.emplace_back(OutSec, next(), Keep); 478481c2ce6SGeorge Rimar } 479481c2ce6SGeorge Rimar 480652852c5SGeorge Rimar void ScriptParser::readLocationCounterValue() { 481652852c5SGeorge Rimar expect("."); 482652852c5SGeorge Rimar expect("="); 4839e957a0aSRui Ueyama Script->Commands.push_back({ExprKind, {}, ""}); 4849e957a0aSRui Ueyama SectionsCommand &Cmd = Script->Commands.back(); 485652852c5SGeorge Rimar while (!Error) { 486652852c5SGeorge Rimar StringRef Tok = next(); 487652852c5SGeorge Rimar if (Tok == ";") 488652852c5SGeorge Rimar break; 4899e957a0aSRui Ueyama Cmd.Expr.push_back(Tok); 490652852c5SGeorge Rimar } 4919e957a0aSRui Ueyama if (Cmd.Expr.empty()) 492652852c5SGeorge Rimar error("error in location counter expression"); 493652852c5SGeorge Rimar } 494652852c5SGeorge Rimar 495717677afSRui Ueyama void ScriptParser::readOutputSectionDescription() { 4963e808976SRui Ueyama StringRef OutSec = next(); 4973e808976SRui Ueyama Script->SectionOrder.push_back(OutSec); 4989e957a0aSRui Ueyama Script->Commands.push_back({SectionKind, {}, OutSec}); 4998e3b38abSDenis Protivensky expect(":"); 5008e3b38abSDenis Protivensky expect("{"); 501025d59b1SRui Ueyama while (!Error && !skip("}")) { 502481c2ce6SGeorge Rimar StringRef Tok = next(); 503481c2ce6SGeorge Rimar if (Tok == "*") { 5043e808976SRui Ueyama readSectionPatterns(OutSec, false); 505481c2ce6SGeorge Rimar } else if (Tok == "KEEP") { 5068e3b38abSDenis Protivensky expect("("); 507481c2ce6SGeorge Rimar next(); // Skip * 5083e808976SRui Ueyama readSectionPatterns(OutSec, true); 509481c2ce6SGeorge Rimar expect(")"); 510481c2ce6SGeorge Rimar } else { 511777f9630SGeorge Rimar setError("unknown command " + Tok); 512481c2ce6SGeorge Rimar } 5138e3b38abSDenis Protivensky } 514e2ee72b5SGeorge Rimar StringRef Tok = peek(); 515e2ee72b5SGeorge Rimar if (Tok.startswith("=")) { 516e2ee72b5SGeorge Rimar if (!Tok.startswith("=0x")) { 5173ed2f069SRui Ueyama setError("filler should be a hexadecimal value"); 518e2ee72b5SGeorge Rimar return; 519e2ee72b5SGeorge Rimar } 5203e808976SRui Ueyama Tok = Tok.substr(3); 5213e808976SRui Ueyama Script->Filler[OutSec] = parseHex(Tok); 522e2ee72b5SGeorge Rimar next(); 523e2ee72b5SGeorge Rimar } 5248e3b38abSDenis Protivensky } 5258e3b38abSDenis Protivensky 52616b0cc9eSSimon Atanasyan static bool isUnderSysroot(StringRef Path) { 52716b0cc9eSSimon Atanasyan if (Config->Sysroot == "") 52816b0cc9eSSimon Atanasyan return false; 52916b0cc9eSSimon Atanasyan for (; !Path.empty(); Path = sys::path::parent_path(Path)) 53016b0cc9eSSimon Atanasyan if (sys::fs::equivalent(Config->Sysroot, Path)) 53116b0cc9eSSimon Atanasyan return true; 53216b0cc9eSSimon Atanasyan return false; 53316b0cc9eSSimon Atanasyan } 53416b0cc9eSSimon Atanasyan 535f7c5fbb1SRui Ueyama // Entry point. The other functions or classes are private to this file. 536f9de0d69SRui Ueyama void LinkerScript::read(MemoryBufferRef MB) { 53716b0cc9eSSimon Atanasyan StringRef Path = MB.getBufferIdentifier(); 538f9de0d69SRui Ueyama ScriptParser(&Alloc, MB.getBuffer(), isUnderSysroot(Path)).run(); 539f7c5fbb1SRui Ueyama } 5401ebc8ed7SRui Ueyama 5411ebc8ed7SRui Ueyama template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF32LE> *); 5421ebc8ed7SRui Ueyama template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF32BE> *); 5431ebc8ed7SRui Ueyama template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF64LE> *); 5441ebc8ed7SRui Ueyama template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF64BE> *); 5451ebc8ed7SRui Ueyama 5461ebc8ed7SRui Ueyama template bool LinkerScript::isDiscarded(InputSectionBase<ELF32LE> *); 5471ebc8ed7SRui Ueyama template bool LinkerScript::isDiscarded(InputSectionBase<ELF32BE> *); 5481ebc8ed7SRui Ueyama template bool LinkerScript::isDiscarded(InputSectionBase<ELF64LE> *); 5491ebc8ed7SRui Ueyama template bool LinkerScript::isDiscarded(InputSectionBase<ELF64BE> *); 5501ebc8ed7SRui Ueyama 551481c2ce6SGeorge Rimar template bool LinkerScript::shouldKeep(InputSectionBase<ELF32LE> *); 552481c2ce6SGeorge Rimar template bool LinkerScript::shouldKeep(InputSectionBase<ELF32BE> *); 553481c2ce6SGeorge Rimar template bool LinkerScript::shouldKeep(InputSectionBase<ELF64LE> *); 554481c2ce6SGeorge Rimar template bool LinkerScript::shouldKeep(InputSectionBase<ELF64BE> *); 555652852c5SGeorge Rimar 556652852c5SGeorge Rimar template void 557652852c5SGeorge Rimar LinkerScript::assignAddresses(std::vector<OutputSectionBase<ELF32LE> *> &); 558652852c5SGeorge Rimar template void 559652852c5SGeorge Rimar LinkerScript::assignAddresses(std::vector<OutputSectionBase<ELF32BE> *> &); 560652852c5SGeorge Rimar template void 561652852c5SGeorge Rimar LinkerScript::assignAddresses(std::vector<OutputSectionBase<ELF64LE> *> &); 562652852c5SGeorge Rimar template void 563652852c5SGeorge Rimar LinkerScript::assignAddresses(std::vector<OutputSectionBase<ELF64BE> *> &); 564