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" 20f7c5fbb1SRui Ueyama #include "SymbolTable.h" 21f7c5fbb1SRui Ueyama #include "llvm/Support/FileSystem.h" 22f7c5fbb1SRui Ueyama #include "llvm/Support/MemoryBuffer.h" 23f03f3cc1SRui Ueyama #include "llvm/Support/Path.h" 24a47ee68dSRui Ueyama #include "llvm/Support/StringSaver.h" 25f7c5fbb1SRui Ueyama 26f7c5fbb1SRui Ueyama using namespace llvm; 271ebc8ed7SRui Ueyama using namespace llvm::object; 28f7c5fbb1SRui Ueyama using namespace lld; 29f7c5fbb1SRui Ueyama using namespace lld::elf2; 30f7c5fbb1SRui Ueyama 31717677afSRui Ueyama LinkerScript *elf2::Script; 32717677afSRui Ueyama 331ebc8ed7SRui Ueyama template <class ELFT> 341ebc8ed7SRui Ueyama StringRef LinkerScript::getOutputSection(InputSectionBase<ELFT> *S) { 351ebc8ed7SRui Ueyama for (SectionRule &R : Sections) 361ebc8ed7SRui Ueyama if (R.match(S)) 371ebc8ed7SRui Ueyama return R.Dest; 381ebc8ed7SRui Ueyama return ""; 39717677afSRui Ueyama } 40717677afSRui Ueyama 411ebc8ed7SRui Ueyama template <class ELFT> 421ebc8ed7SRui Ueyama bool LinkerScript::isDiscarded(InputSectionBase<ELFT> *S) { 431ebc8ed7SRui Ueyama return getOutputSection(S) == "/DISCARD/"; 44717677afSRui Ueyama } 45717677afSRui Ueyama 46e9c58065SRui Ueyama // A compartor to sort output sections. Returns -1 or 1 if both 47e9c58065SRui Ueyama // A and B are mentioned in linker scripts. Otherwise, returns 0 48e9c58065SRui Ueyama // to use the default rule which is implemented in Writer.cpp. 49717677afSRui Ueyama int LinkerScript::compareSections(StringRef A, StringRef B) { 50e9c58065SRui Ueyama auto E = SectionOrder.end(); 51e9c58065SRui Ueyama auto I = std::find(SectionOrder.begin(), E, A); 52e9c58065SRui Ueyama auto J = std::find(SectionOrder.begin(), E, B); 53e9c58065SRui Ueyama if (I == E || J == E) 54717677afSRui Ueyama return 0; 55717677afSRui Ueyama return I < J ? -1 : 1; 56717677afSRui Ueyama } 57717677afSRui Ueyama 581ebc8ed7SRui Ueyama // Returns true if S matches T. S may contain a meta character '*' 591ebc8ed7SRui Ueyama // which matches zero or more occurrences of any character. 601ebc8ed7SRui Ueyama static bool matchStr(StringRef S, StringRef T) { 611ebc8ed7SRui Ueyama for (;;) { 621ebc8ed7SRui Ueyama if (S.empty()) 631ebc8ed7SRui Ueyama return T.empty(); 641ebc8ed7SRui Ueyama if (S[0] == '*') { 651ebc8ed7SRui Ueyama S = S.substr(1); 661ebc8ed7SRui Ueyama if (S.empty()) 671ebc8ed7SRui Ueyama // Fast path. If a pattern is '*', it matches anything. 681ebc8ed7SRui Ueyama return true; 691ebc8ed7SRui Ueyama for (size_t I = 0, E = T.size(); I < E; ++I) 701ebc8ed7SRui Ueyama if (matchStr(S, T.substr(I))) 711ebc8ed7SRui Ueyama return true; 721ebc8ed7SRui Ueyama return false; 731ebc8ed7SRui Ueyama } 741ebc8ed7SRui Ueyama if (T.empty() || S[0] != T[0]) 751ebc8ed7SRui Ueyama return false; 761ebc8ed7SRui Ueyama S = S.substr(1); 771ebc8ed7SRui Ueyama T = T.substr(1); 781ebc8ed7SRui Ueyama } 791ebc8ed7SRui Ueyama } 801ebc8ed7SRui Ueyama 811ebc8ed7SRui Ueyama template <class ELFT> bool SectionRule::match(InputSectionBase<ELFT> *S) { 821ebc8ed7SRui Ueyama return matchStr(SectionPattern, S->getSectionName()); 831ebc8ed7SRui Ueyama } 841ebc8ed7SRui Ueyama 85717677afSRui Ueyama class elf2::ScriptParser { 86f7c5fbb1SRui Ueyama public: 87717677afSRui Ueyama ScriptParser(BumpPtrAllocator *A, StringRef S, bool B) 88f23b2320SGeorge Rimar : Saver(*A), Tokens(tokenize(S)), IsUnderSysroot(B) { 89*d2389bfdSGeorge Rimar Cmd["ENTRY"] = std::mem_fn(&ScriptParser::readEntry); 90*d2389bfdSGeorge Rimar Cmd["EXTERN"] = std::mem_fn(&ScriptParser::readExtern); 91*d2389bfdSGeorge Rimar Cmd["GROUP"] = std::mem_fn(&ScriptParser::readGroup); 92*d2389bfdSGeorge Rimar Cmd["INCLUDE"] = std::mem_fn(&ScriptParser::readInclude); 93*d2389bfdSGeorge Rimar Cmd["INPUT"] = std::mem_fn(&ScriptParser::readGroup); 94*d2389bfdSGeorge Rimar Cmd["OUTPUT"] = std::mem_fn(&ScriptParser::readOutput); 95*d2389bfdSGeorge Rimar Cmd["OUTPUT_ARCH"] = std::mem_fn(&ScriptParser::readOutputArch); 96*d2389bfdSGeorge Rimar Cmd["OUTPUT_FORMAT"] = std::mem_fn(&ScriptParser::readOutputFormat); 97*d2389bfdSGeorge Rimar Cmd["SEARCH_DIR"] = std::mem_fn(&ScriptParser::readSearchDir); 98*d2389bfdSGeorge Rimar Cmd["SECTIONS"] = std::mem_fn(&ScriptParser::readSections); 99f23b2320SGeorge Rimar Cmd[";"] = [](ScriptParser &) {}; 100f23b2320SGeorge Rimar } 101f23b2320SGeorge Rimar 102f7c5fbb1SRui Ueyama void run(); 103f7c5fbb1SRui Ueyama 104f7c5fbb1SRui Ueyama private: 105025d59b1SRui Ueyama void setError(const Twine &Msg); 106f7c5fbb1SRui Ueyama static std::vector<StringRef> tokenize(StringRef S); 107f7c5fbb1SRui Ueyama static StringRef skipSpace(StringRef S); 108025d59b1SRui Ueyama bool atEOF(); 109f7c5fbb1SRui Ueyama StringRef next(); 1108e3b38abSDenis Protivensky bool skip(StringRef Tok); 111f7c5fbb1SRui Ueyama void expect(StringRef Expect); 112f7c5fbb1SRui Ueyama 11352a1509eSRui Ueyama void addFile(StringRef Path); 11452a1509eSRui Ueyama 115f7c5fbb1SRui Ueyama void readAsNeeded(); 11690c5099eSDenis Protivensky void readEntry(); 11783f406cfSGeorge Rimar void readExtern(); 118f7c5fbb1SRui Ueyama void readGroup(); 11931aa1f83SRui Ueyama void readInclude(); 120ee59282bSRui Ueyama void readOutput(); 1219159ce93SDavide Italiano void readOutputArch(); 122f7c5fbb1SRui Ueyama void readOutputFormat(); 12368a39a65SDavide Italiano void readSearchDir(); 1248e3b38abSDenis Protivensky void readSections(); 1258e3b38abSDenis Protivensky 1268e3b38abSDenis Protivensky void readOutputSectionDescription(); 127f7c5fbb1SRui Ueyama 128a47ee68dSRui Ueyama StringSaver Saver; 129f7c5fbb1SRui Ueyama std::vector<StringRef> Tokens; 130f23b2320SGeorge Rimar llvm::StringMap<std::function<void(ScriptParser &)>> Cmd; 131f7c5fbb1SRui Ueyama size_t Pos = 0; 13216b0cc9eSSimon Atanasyan bool IsUnderSysroot; 133f23b2320SGeorge Rimar bool Error = false; 134f7c5fbb1SRui Ueyama }; 135f7c5fbb1SRui Ueyama 136717677afSRui Ueyama void ScriptParser::run() { 137f7c5fbb1SRui Ueyama while (!atEOF()) { 138f7c5fbb1SRui Ueyama StringRef Tok = next(); 139f23b2320SGeorge Rimar auto It = Cmd.find(Tok); 140f23b2320SGeorge Rimar if (It != Cmd.end()) { 141f23b2320SGeorge Rimar std::function<void(ScriptParser &)> &Handler = It->second; 142f23b2320SGeorge Rimar Handler(*this); 143f7c5fbb1SRui Ueyama } else { 144025d59b1SRui Ueyama setError("unknown directive: " + Tok); 145f7c5fbb1SRui Ueyama } 146f7c5fbb1SRui Ueyama } 147f7c5fbb1SRui Ueyama } 148f7c5fbb1SRui Ueyama 149025d59b1SRui Ueyama // We don't want to record cascading errors. Keep only the first one. 150717677afSRui Ueyama void ScriptParser::setError(const Twine &Msg) { 151025d59b1SRui Ueyama if (Error) 152025d59b1SRui Ueyama return; 153025d59b1SRui Ueyama error(Msg); 154025d59b1SRui Ueyama Error = true; 155025d59b1SRui Ueyama } 156025d59b1SRui Ueyama 157f7c5fbb1SRui Ueyama // Split S into linker script tokens. 158717677afSRui Ueyama std::vector<StringRef> ScriptParser::tokenize(StringRef S) { 159f7c5fbb1SRui Ueyama std::vector<StringRef> Ret; 160f7c5fbb1SRui Ueyama for (;;) { 161f7c5fbb1SRui Ueyama S = skipSpace(S); 162f7c5fbb1SRui Ueyama if (S.empty()) 163f7c5fbb1SRui Ueyama return Ret; 164f7c5fbb1SRui Ueyama 165f7c5fbb1SRui Ueyama // Quoted token 166f7c5fbb1SRui Ueyama if (S.startswith("\"")) { 167f7c5fbb1SRui Ueyama size_t E = S.find("\"", 1); 168025d59b1SRui Ueyama if (E == StringRef::npos) { 169025d59b1SRui Ueyama error("unclosed quote"); 170025d59b1SRui Ueyama return {}; 171025d59b1SRui Ueyama } 17260259337SPete Cooper Ret.push_back(S.substr(1, E - 1)); 173f7c5fbb1SRui Ueyama S = S.substr(E + 1); 174f7c5fbb1SRui Ueyama continue; 175f7c5fbb1SRui Ueyama } 176f7c5fbb1SRui Ueyama 177f7c5fbb1SRui Ueyama // Unquoted token 178f7c5fbb1SRui Ueyama size_t Pos = S.find_first_not_of( 179f7c5fbb1SRui Ueyama "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 180f7c5fbb1SRui Ueyama "0123456789_.$/\\~=+[]*?-:"); 181f7c5fbb1SRui Ueyama // A character that cannot start a word (which is usually a 182f7c5fbb1SRui Ueyama // punctuation) forms a single character token. 183f7c5fbb1SRui Ueyama if (Pos == 0) 184f7c5fbb1SRui Ueyama Pos = 1; 185f7c5fbb1SRui Ueyama Ret.push_back(S.substr(0, Pos)); 186f7c5fbb1SRui Ueyama S = S.substr(Pos); 187f7c5fbb1SRui Ueyama } 188f7c5fbb1SRui Ueyama } 189f7c5fbb1SRui Ueyama 190f7c5fbb1SRui Ueyama // Skip leading whitespace characters or /**/-style comments. 191717677afSRui Ueyama StringRef ScriptParser::skipSpace(StringRef S) { 192f7c5fbb1SRui Ueyama for (;;) { 193f7c5fbb1SRui Ueyama if (S.startswith("/*")) { 194f7c5fbb1SRui Ueyama size_t E = S.find("*/", 2); 195025d59b1SRui Ueyama if (E == StringRef::npos) { 196025d59b1SRui Ueyama error("unclosed comment in a linker script"); 197025d59b1SRui Ueyama return ""; 198025d59b1SRui Ueyama } 199f7c5fbb1SRui Ueyama S = S.substr(E + 2); 200f7c5fbb1SRui Ueyama continue; 201f7c5fbb1SRui Ueyama } 202f7c5fbb1SRui Ueyama size_t Size = S.size(); 203f7c5fbb1SRui Ueyama S = S.ltrim(); 204f7c5fbb1SRui Ueyama if (S.size() == Size) 205f7c5fbb1SRui Ueyama return S; 206f7c5fbb1SRui Ueyama } 207f7c5fbb1SRui Ueyama } 208f7c5fbb1SRui Ueyama 209025d59b1SRui Ueyama // An errneous token is handled as if it were the last token before EOF. 210717677afSRui Ueyama bool ScriptParser::atEOF() { return Error || Tokens.size() == Pos; } 211025d59b1SRui Ueyama 212717677afSRui Ueyama StringRef ScriptParser::next() { 213025d59b1SRui Ueyama if (Error) 214025d59b1SRui Ueyama return ""; 215025d59b1SRui Ueyama if (atEOF()) { 216025d59b1SRui Ueyama setError("unexpected EOF"); 217025d59b1SRui Ueyama return ""; 218025d59b1SRui Ueyama } 219f7c5fbb1SRui Ueyama return Tokens[Pos++]; 220f7c5fbb1SRui Ueyama } 221f7c5fbb1SRui Ueyama 222717677afSRui Ueyama bool ScriptParser::skip(StringRef Tok) { 223025d59b1SRui Ueyama if (Error) 224025d59b1SRui Ueyama return false; 225025d59b1SRui Ueyama if (atEOF()) { 226025d59b1SRui Ueyama setError("unexpected EOF"); 227025d59b1SRui Ueyama return false; 228025d59b1SRui Ueyama } 2298e3b38abSDenis Protivensky if (Tok != Tokens[Pos]) 2308e3b38abSDenis Protivensky return false; 2318e3b38abSDenis Protivensky ++Pos; 2328e3b38abSDenis Protivensky return true; 2338e3b38abSDenis Protivensky } 2348e3b38abSDenis Protivensky 235717677afSRui Ueyama void ScriptParser::expect(StringRef Expect) { 236025d59b1SRui Ueyama if (Error) 237025d59b1SRui Ueyama return; 238f7c5fbb1SRui Ueyama StringRef Tok = next(); 239f7c5fbb1SRui Ueyama if (Tok != Expect) 240025d59b1SRui Ueyama setError(Expect + " expected, but got " + Tok); 241f7c5fbb1SRui Ueyama } 242f7c5fbb1SRui Ueyama 243717677afSRui Ueyama void ScriptParser::addFile(StringRef S) { 24416b0cc9eSSimon Atanasyan if (IsUnderSysroot && S.startswith("/")) { 24516b0cc9eSSimon Atanasyan SmallString<128> Path; 24616b0cc9eSSimon Atanasyan (Config->Sysroot + S).toStringRef(Path); 24716b0cc9eSSimon Atanasyan if (sys::fs::exists(Path)) { 24816b0cc9eSSimon Atanasyan Driver->addFile(Saver.save(Path.str())); 24916b0cc9eSSimon Atanasyan return; 25016b0cc9eSSimon Atanasyan } 25116b0cc9eSSimon Atanasyan } 25216b0cc9eSSimon Atanasyan 253f03f3cc1SRui Ueyama if (sys::path::is_absolute(S)) { 25452a1509eSRui Ueyama Driver->addFile(S); 25552a1509eSRui Ueyama } else if (S.startswith("=")) { 25652a1509eSRui Ueyama if (Config->Sysroot.empty()) 25752a1509eSRui Ueyama Driver->addFile(S.substr(1)); 25852a1509eSRui Ueyama else 25952a1509eSRui Ueyama Driver->addFile(Saver.save(Config->Sysroot + "/" + S.substr(1))); 26052a1509eSRui Ueyama } else if (S.startswith("-l")) { 26121eecb4fSRui Ueyama Driver->addLibrary(S.substr(2)); 262a1b8fc3bSSimon Atanasyan } else if (sys::fs::exists(S)) { 263a1b8fc3bSSimon Atanasyan Driver->addFile(S); 26452a1509eSRui Ueyama } else { 26552a1509eSRui Ueyama std::string Path = findFromSearchPaths(S); 26652a1509eSRui Ueyama if (Path.empty()) 267025d59b1SRui Ueyama setError("Unable to find " + S); 268025d59b1SRui Ueyama else 26952a1509eSRui Ueyama Driver->addFile(Saver.save(Path)); 27052a1509eSRui Ueyama } 27152a1509eSRui Ueyama } 27252a1509eSRui Ueyama 273717677afSRui Ueyama void ScriptParser::readAsNeeded() { 274f7c5fbb1SRui Ueyama expect("("); 27535da9b6eSRui Ueyama bool Orig = Config->AsNeeded; 27635da9b6eSRui Ueyama Config->AsNeeded = true; 277025d59b1SRui Ueyama while (!Error) { 278f7c5fbb1SRui Ueyama StringRef Tok = next(); 279f7c5fbb1SRui Ueyama if (Tok == ")") 28035da9b6eSRui Ueyama break; 28152a1509eSRui Ueyama addFile(Tok); 282f7c5fbb1SRui Ueyama } 28335da9b6eSRui Ueyama Config->AsNeeded = Orig; 284f7c5fbb1SRui Ueyama } 285f7c5fbb1SRui Ueyama 286717677afSRui Ueyama void ScriptParser::readEntry() { 28790c5099eSDenis Protivensky // -e <symbol> takes predecence over ENTRY(<symbol>). 28890c5099eSDenis Protivensky expect("("); 28990c5099eSDenis Protivensky StringRef Tok = next(); 29090c5099eSDenis Protivensky if (Config->Entry.empty()) 29190c5099eSDenis Protivensky Config->Entry = Tok; 29290c5099eSDenis Protivensky expect(")"); 29390c5099eSDenis Protivensky } 29490c5099eSDenis Protivensky 295717677afSRui Ueyama void ScriptParser::readExtern() { 29683f406cfSGeorge Rimar expect("("); 297025d59b1SRui Ueyama while (!Error) { 29883f406cfSGeorge Rimar StringRef Tok = next(); 29983f406cfSGeorge Rimar if (Tok == ")") 30083f406cfSGeorge Rimar return; 30183f406cfSGeorge Rimar Config->Undefined.push_back(Tok); 30283f406cfSGeorge Rimar } 30383f406cfSGeorge Rimar } 30483f406cfSGeorge Rimar 305717677afSRui Ueyama void ScriptParser::readGroup() { 306f7c5fbb1SRui Ueyama expect("("); 307025d59b1SRui Ueyama while (!Error) { 308f7c5fbb1SRui Ueyama StringRef Tok = next(); 309f7c5fbb1SRui Ueyama if (Tok == ")") 310f7c5fbb1SRui Ueyama return; 311f7c5fbb1SRui Ueyama if (Tok == "AS_NEEDED") { 312f7c5fbb1SRui Ueyama readAsNeeded(); 313f7c5fbb1SRui Ueyama continue; 314f7c5fbb1SRui Ueyama } 31552a1509eSRui Ueyama addFile(Tok); 316f7c5fbb1SRui Ueyama } 317f7c5fbb1SRui Ueyama } 318f7c5fbb1SRui Ueyama 319717677afSRui Ueyama void ScriptParser::readInclude() { 32031aa1f83SRui Ueyama StringRef Tok = next(); 32131aa1f83SRui Ueyama auto MBOrErr = MemoryBuffer::getFile(Tok); 322025d59b1SRui Ueyama if (!MBOrErr) { 323025d59b1SRui Ueyama setError("cannot open " + Tok); 324025d59b1SRui Ueyama return; 325025d59b1SRui Ueyama } 32631aa1f83SRui Ueyama std::unique_ptr<MemoryBuffer> &MB = *MBOrErr; 327a47ee68dSRui Ueyama StringRef S = Saver.save(MB->getMemBufferRef().getBuffer()); 328a47ee68dSRui Ueyama std::vector<StringRef> V = tokenize(S); 32931aa1f83SRui Ueyama Tokens.insert(Tokens.begin() + Pos, V.begin(), V.end()); 33031aa1f83SRui Ueyama } 33131aa1f83SRui Ueyama 332717677afSRui Ueyama void ScriptParser::readOutput() { 333ee59282bSRui Ueyama // -o <file> takes predecence over OUTPUT(<file>). 334ee59282bSRui Ueyama expect("("); 335ee59282bSRui Ueyama StringRef Tok = next(); 336ee59282bSRui Ueyama if (Config->OutputFile.empty()) 337ee59282bSRui Ueyama Config->OutputFile = Tok; 338ee59282bSRui Ueyama expect(")"); 339ee59282bSRui Ueyama } 340ee59282bSRui Ueyama 341717677afSRui Ueyama void ScriptParser::readOutputArch() { 3429159ce93SDavide Italiano // Error checking only for now. 3439159ce93SDavide Italiano expect("("); 3449159ce93SDavide Italiano next(); 3459159ce93SDavide Italiano expect(")"); 3469159ce93SDavide Italiano } 3479159ce93SDavide Italiano 348717677afSRui Ueyama void ScriptParser::readOutputFormat() { 349f7c5fbb1SRui Ueyama // Error checking only for now. 350f7c5fbb1SRui Ueyama expect("("); 351f7c5fbb1SRui Ueyama next(); 3526836c618SDavide Italiano StringRef Tok = next(); 3536836c618SDavide Italiano if (Tok == ")") 3546836c618SDavide Italiano return; 355025d59b1SRui Ueyama if (Tok != ",") { 356025d59b1SRui Ueyama setError("unexpected token: " + Tok); 357025d59b1SRui Ueyama return; 358025d59b1SRui Ueyama } 3596836c618SDavide Italiano next(); 3606836c618SDavide Italiano expect(","); 3616836c618SDavide Italiano next(); 362f7c5fbb1SRui Ueyama expect(")"); 363f7c5fbb1SRui Ueyama } 364f7c5fbb1SRui Ueyama 365717677afSRui Ueyama void ScriptParser::readSearchDir() { 36668a39a65SDavide Italiano expect("("); 36752a1509eSRui Ueyama Config->SearchPaths.push_back(next()); 36868a39a65SDavide Italiano expect(")"); 36968a39a65SDavide Italiano } 37068a39a65SDavide Italiano 371717677afSRui Ueyama void ScriptParser::readSections() { 3728e3b38abSDenis Protivensky expect("{"); 373025d59b1SRui Ueyama while (!Error && !skip("}")) 3748e3b38abSDenis Protivensky readOutputSectionDescription(); 3758e3b38abSDenis Protivensky } 3768e3b38abSDenis Protivensky 377717677afSRui Ueyama void ScriptParser::readOutputSectionDescription() { 378e9c58065SRui Ueyama StringRef OutSec = next(); 379e9c58065SRui Ueyama Script->SectionOrder.push_back(OutSec); 3808e3b38abSDenis Protivensky expect(":"); 3818e3b38abSDenis Protivensky expect("{"); 382025d59b1SRui Ueyama while (!Error && !skip("}")) { 3838e3b38abSDenis Protivensky next(); // Skip input file name. 3848e3b38abSDenis Protivensky expect("("); 385025d59b1SRui Ueyama while (!Error && !skip(")")) 3861ebc8ed7SRui Ueyama Script->Sections.push_back({OutSec, next()}); 3878e3b38abSDenis Protivensky } 3888e3b38abSDenis Protivensky } 3898e3b38abSDenis Protivensky 39016b0cc9eSSimon Atanasyan static bool isUnderSysroot(StringRef Path) { 39116b0cc9eSSimon Atanasyan if (Config->Sysroot == "") 39216b0cc9eSSimon Atanasyan return false; 39316b0cc9eSSimon Atanasyan for (; !Path.empty(); Path = sys::path::parent_path(Path)) 39416b0cc9eSSimon Atanasyan if (sys::fs::equivalent(Config->Sysroot, Path)) 39516b0cc9eSSimon Atanasyan return true; 39616b0cc9eSSimon Atanasyan return false; 39716b0cc9eSSimon Atanasyan } 39816b0cc9eSSimon Atanasyan 399f7c5fbb1SRui Ueyama // Entry point. The other functions or classes are private to this file. 400f9de0d69SRui Ueyama void LinkerScript::read(MemoryBufferRef MB) { 40116b0cc9eSSimon Atanasyan StringRef Path = MB.getBufferIdentifier(); 402f9de0d69SRui Ueyama ScriptParser(&Alloc, MB.getBuffer(), isUnderSysroot(Path)).run(); 403f7c5fbb1SRui Ueyama } 4041ebc8ed7SRui Ueyama 4051ebc8ed7SRui Ueyama template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF32LE> *); 4061ebc8ed7SRui Ueyama template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF32BE> *); 4071ebc8ed7SRui Ueyama template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF64LE> *); 4081ebc8ed7SRui Ueyama template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF64BE> *); 4091ebc8ed7SRui Ueyama 4101ebc8ed7SRui Ueyama template bool LinkerScript::isDiscarded(InputSectionBase<ELF32LE> *); 4111ebc8ed7SRui Ueyama template bool LinkerScript::isDiscarded(InputSectionBase<ELF32BE> *); 4121ebc8ed7SRui Ueyama template bool LinkerScript::isDiscarded(InputSectionBase<ELF64LE> *); 4131ebc8ed7SRui Ueyama template bool LinkerScript::isDiscarded(InputSectionBase<ELF64BE> *); 4141ebc8ed7SRui Ueyama 4151ebc8ed7SRui Ueyama template bool SectionRule::match(InputSectionBase<ELF32LE> *); 4161ebc8ed7SRui Ueyama template bool SectionRule::match(InputSectionBase<ELF32BE> *); 4171ebc8ed7SRui Ueyama template bool SectionRule::match(InputSectionBase<ELF64LE> *); 4181ebc8ed7SRui Ueyama template bool SectionRule::match(InputSectionBase<ELF64BE> *); 419