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> 34*481c2ce6SGeorge Rimar SectionRule *LinkerScript::find(InputSectionBase<ELFT> *S) { 351ebc8ed7SRui Ueyama for (SectionRule &R : Sections) 361ebc8ed7SRui Ueyama if (R.match(S)) 37*481c2ce6SGeorge Rimar return &R; 38*481c2ce6SGeorge Rimar return nullptr; 39*481c2ce6SGeorge Rimar } 40*481c2ce6SGeorge Rimar 41*481c2ce6SGeorge Rimar template <class ELFT> 42*481c2ce6SGeorge Rimar StringRef LinkerScript::getOutputSection(InputSectionBase<ELFT> *S) { 43*481c2ce6SGeorge Rimar SectionRule *R = find(S); 44*481c2ce6SGeorge Rimar return R ? R->Dest : ""; 45717677afSRui Ueyama } 46717677afSRui Ueyama 471ebc8ed7SRui Ueyama template <class ELFT> 481ebc8ed7SRui Ueyama bool LinkerScript::isDiscarded(InputSectionBase<ELFT> *S) { 491ebc8ed7SRui Ueyama return getOutputSection(S) == "/DISCARD/"; 50717677afSRui Ueyama } 51717677afSRui Ueyama 52*481c2ce6SGeorge Rimar template <class ELFT> bool LinkerScript::shouldKeep(InputSectionBase<ELFT> *S) { 53*481c2ce6SGeorge Rimar SectionRule *R = find(S); 54*481c2ce6SGeorge Rimar return R && R->Keep; 55*481c2ce6SGeorge Rimar } 56*481c2ce6SGeorge Rimar 57e9c58065SRui Ueyama // A compartor to sort output sections. Returns -1 or 1 if both 58e9c58065SRui Ueyama // A and B are mentioned in linker scripts. Otherwise, returns 0 59e9c58065SRui Ueyama // to use the default rule which is implemented in Writer.cpp. 60717677afSRui Ueyama int LinkerScript::compareSections(StringRef A, StringRef B) { 61e9c58065SRui Ueyama auto E = SectionOrder.end(); 62e9c58065SRui Ueyama auto I = std::find(SectionOrder.begin(), E, A); 63e9c58065SRui Ueyama auto J = std::find(SectionOrder.begin(), E, B); 64e9c58065SRui Ueyama if (I == E || J == E) 65717677afSRui Ueyama return 0; 66717677afSRui Ueyama return I < J ? -1 : 1; 67717677afSRui Ueyama } 68717677afSRui Ueyama 691ebc8ed7SRui Ueyama // Returns true if S matches T. S may contain a meta character '*' 701ebc8ed7SRui Ueyama // which matches zero or more occurrences of any character. 711ebc8ed7SRui Ueyama static bool matchStr(StringRef S, StringRef T) { 721ebc8ed7SRui Ueyama for (;;) { 731ebc8ed7SRui Ueyama if (S.empty()) 741ebc8ed7SRui Ueyama return T.empty(); 751ebc8ed7SRui Ueyama if (S[0] == '*') { 761ebc8ed7SRui Ueyama S = S.substr(1); 771ebc8ed7SRui Ueyama if (S.empty()) 781ebc8ed7SRui Ueyama // Fast path. If a pattern is '*', it matches anything. 791ebc8ed7SRui Ueyama return true; 801ebc8ed7SRui Ueyama for (size_t I = 0, E = T.size(); I < E; ++I) 811ebc8ed7SRui Ueyama if (matchStr(S, T.substr(I))) 821ebc8ed7SRui Ueyama return true; 831ebc8ed7SRui Ueyama return false; 841ebc8ed7SRui Ueyama } 851ebc8ed7SRui Ueyama if (T.empty() || S[0] != T[0]) 861ebc8ed7SRui Ueyama return false; 871ebc8ed7SRui Ueyama S = S.substr(1); 881ebc8ed7SRui Ueyama T = T.substr(1); 891ebc8ed7SRui Ueyama } 901ebc8ed7SRui Ueyama } 911ebc8ed7SRui Ueyama 921ebc8ed7SRui Ueyama template <class ELFT> bool SectionRule::match(InputSectionBase<ELFT> *S) { 931ebc8ed7SRui Ueyama return matchStr(SectionPattern, S->getSectionName()); 941ebc8ed7SRui Ueyama } 951ebc8ed7SRui Ueyama 96717677afSRui Ueyama class elf2::ScriptParser { 97f7c5fbb1SRui Ueyama public: 98717677afSRui Ueyama ScriptParser(BumpPtrAllocator *A, StringRef S, bool B) 99f23b2320SGeorge Rimar : Saver(*A), Tokens(tokenize(S)), IsUnderSysroot(B) { 100d2389bfdSGeorge Rimar Cmd["ENTRY"] = std::mem_fn(&ScriptParser::readEntry); 101d2389bfdSGeorge Rimar Cmd["EXTERN"] = std::mem_fn(&ScriptParser::readExtern); 102d2389bfdSGeorge Rimar Cmd["GROUP"] = std::mem_fn(&ScriptParser::readGroup); 103d2389bfdSGeorge Rimar Cmd["INCLUDE"] = std::mem_fn(&ScriptParser::readInclude); 104d2389bfdSGeorge Rimar Cmd["INPUT"] = std::mem_fn(&ScriptParser::readGroup); 105d2389bfdSGeorge Rimar Cmd["OUTPUT"] = std::mem_fn(&ScriptParser::readOutput); 106d2389bfdSGeorge Rimar Cmd["OUTPUT_ARCH"] = std::mem_fn(&ScriptParser::readOutputArch); 107d2389bfdSGeorge Rimar Cmd["OUTPUT_FORMAT"] = std::mem_fn(&ScriptParser::readOutputFormat); 108d2389bfdSGeorge Rimar Cmd["SEARCH_DIR"] = std::mem_fn(&ScriptParser::readSearchDir); 109d2389bfdSGeorge Rimar Cmd["SECTIONS"] = std::mem_fn(&ScriptParser::readSections); 110f23b2320SGeorge Rimar Cmd[";"] = [](ScriptParser &) {}; 111f23b2320SGeorge Rimar } 112f23b2320SGeorge Rimar 113f7c5fbb1SRui Ueyama void run(); 114f7c5fbb1SRui Ueyama 115f7c5fbb1SRui Ueyama private: 116025d59b1SRui Ueyama void setError(const Twine &Msg); 117f7c5fbb1SRui Ueyama static std::vector<StringRef> tokenize(StringRef S); 118f7c5fbb1SRui Ueyama static StringRef skipSpace(StringRef S); 119025d59b1SRui Ueyama bool atEOF(); 120f7c5fbb1SRui Ueyama StringRef next(); 1218e3b38abSDenis Protivensky bool skip(StringRef Tok); 122f7c5fbb1SRui Ueyama void expect(StringRef Expect); 123f7c5fbb1SRui Ueyama 12452a1509eSRui Ueyama void addFile(StringRef Path); 12552a1509eSRui Ueyama 126f7c5fbb1SRui Ueyama void readAsNeeded(); 12790c5099eSDenis Protivensky void readEntry(); 12883f406cfSGeorge Rimar void readExtern(); 129f7c5fbb1SRui Ueyama void readGroup(); 13031aa1f83SRui Ueyama void readInclude(); 131ee59282bSRui Ueyama void readOutput(); 1329159ce93SDavide Italiano void readOutputArch(); 133f7c5fbb1SRui Ueyama void readOutputFormat(); 13468a39a65SDavide Italiano void readSearchDir(); 1358e3b38abSDenis Protivensky void readSections(); 1368e3b38abSDenis Protivensky 1378e3b38abSDenis Protivensky void readOutputSectionDescription(); 138*481c2ce6SGeorge Rimar void readSectionPatterns(StringRef OutSec, bool Keep); 139f7c5fbb1SRui Ueyama 140a47ee68dSRui Ueyama StringSaver Saver; 141f7c5fbb1SRui Ueyama std::vector<StringRef> Tokens; 142f23b2320SGeorge Rimar llvm::StringMap<std::function<void(ScriptParser &)>> Cmd; 143f7c5fbb1SRui Ueyama size_t Pos = 0; 14416b0cc9eSSimon Atanasyan bool IsUnderSysroot; 145f23b2320SGeorge Rimar bool Error = false; 146f7c5fbb1SRui Ueyama }; 147f7c5fbb1SRui Ueyama 148717677afSRui Ueyama void ScriptParser::run() { 149f7c5fbb1SRui Ueyama while (!atEOF()) { 150f7c5fbb1SRui Ueyama StringRef Tok = next(); 151f23b2320SGeorge Rimar auto It = Cmd.find(Tok); 152f23b2320SGeorge Rimar if (It != Cmd.end()) { 153f23b2320SGeorge Rimar std::function<void(ScriptParser &)> &Handler = It->second; 154f23b2320SGeorge Rimar Handler(*this); 155f7c5fbb1SRui Ueyama } else { 156025d59b1SRui Ueyama setError("unknown directive: " + Tok); 157f7c5fbb1SRui Ueyama } 158f7c5fbb1SRui Ueyama } 159f7c5fbb1SRui Ueyama } 160f7c5fbb1SRui Ueyama 161025d59b1SRui Ueyama // We don't want to record cascading errors. Keep only the first one. 162717677afSRui Ueyama void ScriptParser::setError(const Twine &Msg) { 163025d59b1SRui Ueyama if (Error) 164025d59b1SRui Ueyama return; 165025d59b1SRui Ueyama error(Msg); 166025d59b1SRui Ueyama Error = true; 167025d59b1SRui Ueyama } 168025d59b1SRui Ueyama 169f7c5fbb1SRui Ueyama // Split S into linker script tokens. 170717677afSRui Ueyama std::vector<StringRef> ScriptParser::tokenize(StringRef S) { 171f7c5fbb1SRui Ueyama std::vector<StringRef> Ret; 172f7c5fbb1SRui Ueyama for (;;) { 173f7c5fbb1SRui Ueyama S = skipSpace(S); 174f7c5fbb1SRui Ueyama if (S.empty()) 175f7c5fbb1SRui Ueyama return Ret; 176f7c5fbb1SRui Ueyama 177f7c5fbb1SRui Ueyama // Quoted token 178f7c5fbb1SRui Ueyama if (S.startswith("\"")) { 179f7c5fbb1SRui Ueyama size_t E = S.find("\"", 1); 180025d59b1SRui Ueyama if (E == StringRef::npos) { 181025d59b1SRui Ueyama error("unclosed quote"); 182025d59b1SRui Ueyama return {}; 183025d59b1SRui Ueyama } 18460259337SPete Cooper Ret.push_back(S.substr(1, E - 1)); 185f7c5fbb1SRui Ueyama S = S.substr(E + 1); 186f7c5fbb1SRui Ueyama continue; 187f7c5fbb1SRui Ueyama } 188f7c5fbb1SRui Ueyama 189f7c5fbb1SRui Ueyama // Unquoted token 190f7c5fbb1SRui Ueyama size_t Pos = S.find_first_not_of( 191f7c5fbb1SRui Ueyama "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 192f7c5fbb1SRui Ueyama "0123456789_.$/\\~=+[]*?-:"); 193f7c5fbb1SRui Ueyama // A character that cannot start a word (which is usually a 194f7c5fbb1SRui Ueyama // punctuation) forms a single character token. 195f7c5fbb1SRui Ueyama if (Pos == 0) 196f7c5fbb1SRui Ueyama Pos = 1; 197f7c5fbb1SRui Ueyama Ret.push_back(S.substr(0, Pos)); 198f7c5fbb1SRui Ueyama S = S.substr(Pos); 199f7c5fbb1SRui Ueyama } 200f7c5fbb1SRui Ueyama } 201f7c5fbb1SRui Ueyama 202f7c5fbb1SRui Ueyama // Skip leading whitespace characters or /**/-style comments. 203717677afSRui Ueyama StringRef ScriptParser::skipSpace(StringRef S) { 204f7c5fbb1SRui Ueyama for (;;) { 205f7c5fbb1SRui Ueyama if (S.startswith("/*")) { 206f7c5fbb1SRui Ueyama size_t E = S.find("*/", 2); 207025d59b1SRui Ueyama if (E == StringRef::npos) { 208025d59b1SRui Ueyama error("unclosed comment in a linker script"); 209025d59b1SRui Ueyama return ""; 210025d59b1SRui Ueyama } 211f7c5fbb1SRui Ueyama S = S.substr(E + 2); 212f7c5fbb1SRui Ueyama continue; 213f7c5fbb1SRui Ueyama } 214f7c5fbb1SRui Ueyama size_t Size = S.size(); 215f7c5fbb1SRui Ueyama S = S.ltrim(); 216f7c5fbb1SRui Ueyama if (S.size() == Size) 217f7c5fbb1SRui Ueyama return S; 218f7c5fbb1SRui Ueyama } 219f7c5fbb1SRui Ueyama } 220f7c5fbb1SRui Ueyama 221025d59b1SRui Ueyama // An errneous token is handled as if it were the last token before EOF. 222717677afSRui Ueyama bool ScriptParser::atEOF() { return Error || Tokens.size() == Pos; } 223025d59b1SRui Ueyama 224717677afSRui Ueyama StringRef ScriptParser::next() { 225025d59b1SRui Ueyama if (Error) 226025d59b1SRui Ueyama return ""; 227025d59b1SRui Ueyama if (atEOF()) { 228025d59b1SRui Ueyama setError("unexpected EOF"); 229025d59b1SRui Ueyama return ""; 230025d59b1SRui Ueyama } 231f7c5fbb1SRui Ueyama return Tokens[Pos++]; 232f7c5fbb1SRui Ueyama } 233f7c5fbb1SRui Ueyama 234717677afSRui Ueyama bool ScriptParser::skip(StringRef Tok) { 235025d59b1SRui Ueyama if (Error) 236025d59b1SRui Ueyama return false; 237025d59b1SRui Ueyama if (atEOF()) { 238025d59b1SRui Ueyama setError("unexpected EOF"); 239025d59b1SRui Ueyama return false; 240025d59b1SRui Ueyama } 2418e3b38abSDenis Protivensky if (Tok != Tokens[Pos]) 2428e3b38abSDenis Protivensky return false; 2438e3b38abSDenis Protivensky ++Pos; 2448e3b38abSDenis Protivensky return true; 2458e3b38abSDenis Protivensky } 2468e3b38abSDenis Protivensky 247717677afSRui Ueyama void ScriptParser::expect(StringRef Expect) { 248025d59b1SRui Ueyama if (Error) 249025d59b1SRui Ueyama return; 250f7c5fbb1SRui Ueyama StringRef Tok = next(); 251f7c5fbb1SRui Ueyama if (Tok != Expect) 252025d59b1SRui Ueyama setError(Expect + " expected, but got " + Tok); 253f7c5fbb1SRui Ueyama } 254f7c5fbb1SRui Ueyama 255717677afSRui Ueyama void ScriptParser::addFile(StringRef S) { 25616b0cc9eSSimon Atanasyan if (IsUnderSysroot && S.startswith("/")) { 25716b0cc9eSSimon Atanasyan SmallString<128> Path; 25816b0cc9eSSimon Atanasyan (Config->Sysroot + S).toStringRef(Path); 25916b0cc9eSSimon Atanasyan if (sys::fs::exists(Path)) { 26016b0cc9eSSimon Atanasyan Driver->addFile(Saver.save(Path.str())); 26116b0cc9eSSimon Atanasyan return; 26216b0cc9eSSimon Atanasyan } 26316b0cc9eSSimon Atanasyan } 26416b0cc9eSSimon Atanasyan 265f03f3cc1SRui Ueyama if (sys::path::is_absolute(S)) { 26652a1509eSRui Ueyama Driver->addFile(S); 26752a1509eSRui Ueyama } else if (S.startswith("=")) { 26852a1509eSRui Ueyama if (Config->Sysroot.empty()) 26952a1509eSRui Ueyama Driver->addFile(S.substr(1)); 27052a1509eSRui Ueyama else 27152a1509eSRui Ueyama Driver->addFile(Saver.save(Config->Sysroot + "/" + S.substr(1))); 27252a1509eSRui Ueyama } else if (S.startswith("-l")) { 27321eecb4fSRui Ueyama Driver->addLibrary(S.substr(2)); 274a1b8fc3bSSimon Atanasyan } else if (sys::fs::exists(S)) { 275a1b8fc3bSSimon Atanasyan Driver->addFile(S); 27652a1509eSRui Ueyama } else { 27752a1509eSRui Ueyama std::string Path = findFromSearchPaths(S); 27852a1509eSRui Ueyama if (Path.empty()) 279025d59b1SRui Ueyama setError("Unable to find " + S); 280025d59b1SRui Ueyama else 28152a1509eSRui Ueyama Driver->addFile(Saver.save(Path)); 28252a1509eSRui Ueyama } 28352a1509eSRui Ueyama } 28452a1509eSRui Ueyama 285717677afSRui Ueyama void ScriptParser::readAsNeeded() { 286f7c5fbb1SRui Ueyama expect("("); 28735da9b6eSRui Ueyama bool Orig = Config->AsNeeded; 28835da9b6eSRui Ueyama Config->AsNeeded = true; 289025d59b1SRui Ueyama while (!Error) { 290f7c5fbb1SRui Ueyama StringRef Tok = next(); 291f7c5fbb1SRui Ueyama if (Tok == ")") 29235da9b6eSRui Ueyama break; 29352a1509eSRui Ueyama addFile(Tok); 294f7c5fbb1SRui Ueyama } 29535da9b6eSRui Ueyama Config->AsNeeded = Orig; 296f7c5fbb1SRui Ueyama } 297f7c5fbb1SRui Ueyama 298717677afSRui Ueyama void ScriptParser::readEntry() { 29990c5099eSDenis Protivensky // -e <symbol> takes predecence over ENTRY(<symbol>). 30090c5099eSDenis Protivensky expect("("); 30190c5099eSDenis Protivensky StringRef Tok = next(); 30290c5099eSDenis Protivensky if (Config->Entry.empty()) 30390c5099eSDenis Protivensky Config->Entry = Tok; 30490c5099eSDenis Protivensky expect(")"); 30590c5099eSDenis Protivensky } 30690c5099eSDenis Protivensky 307717677afSRui Ueyama void ScriptParser::readExtern() { 30883f406cfSGeorge Rimar expect("("); 309025d59b1SRui Ueyama while (!Error) { 31083f406cfSGeorge Rimar StringRef Tok = next(); 31183f406cfSGeorge Rimar if (Tok == ")") 31283f406cfSGeorge Rimar return; 31383f406cfSGeorge Rimar Config->Undefined.push_back(Tok); 31483f406cfSGeorge Rimar } 31583f406cfSGeorge Rimar } 31683f406cfSGeorge Rimar 317717677afSRui Ueyama void ScriptParser::readGroup() { 318f7c5fbb1SRui Ueyama expect("("); 319025d59b1SRui Ueyama while (!Error) { 320f7c5fbb1SRui Ueyama StringRef Tok = next(); 321f7c5fbb1SRui Ueyama if (Tok == ")") 322f7c5fbb1SRui Ueyama return; 323f7c5fbb1SRui Ueyama if (Tok == "AS_NEEDED") { 324f7c5fbb1SRui Ueyama readAsNeeded(); 325f7c5fbb1SRui Ueyama continue; 326f7c5fbb1SRui Ueyama } 32752a1509eSRui Ueyama addFile(Tok); 328f7c5fbb1SRui Ueyama } 329f7c5fbb1SRui Ueyama } 330f7c5fbb1SRui Ueyama 331717677afSRui Ueyama void ScriptParser::readInclude() { 33231aa1f83SRui Ueyama StringRef Tok = next(); 33331aa1f83SRui Ueyama auto MBOrErr = MemoryBuffer::getFile(Tok); 334025d59b1SRui Ueyama if (!MBOrErr) { 335025d59b1SRui Ueyama setError("cannot open " + Tok); 336025d59b1SRui Ueyama return; 337025d59b1SRui Ueyama } 33831aa1f83SRui Ueyama std::unique_ptr<MemoryBuffer> &MB = *MBOrErr; 339a47ee68dSRui Ueyama StringRef S = Saver.save(MB->getMemBufferRef().getBuffer()); 340a47ee68dSRui Ueyama std::vector<StringRef> V = tokenize(S); 34131aa1f83SRui Ueyama Tokens.insert(Tokens.begin() + Pos, V.begin(), V.end()); 34231aa1f83SRui Ueyama } 34331aa1f83SRui Ueyama 344717677afSRui Ueyama void ScriptParser::readOutput() { 345ee59282bSRui Ueyama // -o <file> takes predecence over OUTPUT(<file>). 346ee59282bSRui Ueyama expect("("); 347ee59282bSRui Ueyama StringRef Tok = next(); 348ee59282bSRui Ueyama if (Config->OutputFile.empty()) 349ee59282bSRui Ueyama Config->OutputFile = Tok; 350ee59282bSRui Ueyama expect(")"); 351ee59282bSRui Ueyama } 352ee59282bSRui Ueyama 353717677afSRui Ueyama void ScriptParser::readOutputArch() { 3549159ce93SDavide Italiano // Error checking only for now. 3559159ce93SDavide Italiano expect("("); 3569159ce93SDavide Italiano next(); 3579159ce93SDavide Italiano expect(")"); 3589159ce93SDavide Italiano } 3599159ce93SDavide Italiano 360717677afSRui Ueyama void ScriptParser::readOutputFormat() { 361f7c5fbb1SRui Ueyama // Error checking only for now. 362f7c5fbb1SRui Ueyama expect("("); 363f7c5fbb1SRui Ueyama next(); 3646836c618SDavide Italiano StringRef Tok = next(); 3656836c618SDavide Italiano if (Tok == ")") 3666836c618SDavide Italiano return; 367025d59b1SRui Ueyama if (Tok != ",") { 368025d59b1SRui Ueyama setError("unexpected token: " + Tok); 369025d59b1SRui Ueyama return; 370025d59b1SRui Ueyama } 3716836c618SDavide Italiano next(); 3726836c618SDavide Italiano expect(","); 3736836c618SDavide Italiano next(); 374f7c5fbb1SRui Ueyama expect(")"); 375f7c5fbb1SRui Ueyama } 376f7c5fbb1SRui Ueyama 377717677afSRui Ueyama void ScriptParser::readSearchDir() { 37868a39a65SDavide Italiano expect("("); 37952a1509eSRui Ueyama Config->SearchPaths.push_back(next()); 38068a39a65SDavide Italiano expect(")"); 38168a39a65SDavide Italiano } 38268a39a65SDavide Italiano 383717677afSRui Ueyama void ScriptParser::readSections() { 3848e3b38abSDenis Protivensky expect("{"); 385025d59b1SRui Ueyama while (!Error && !skip("}")) 3868e3b38abSDenis Protivensky readOutputSectionDescription(); 3878e3b38abSDenis Protivensky } 3888e3b38abSDenis Protivensky 389*481c2ce6SGeorge Rimar void ScriptParser::readSectionPatterns(StringRef OutSec, bool Keep) { 390*481c2ce6SGeorge Rimar expect("("); 391*481c2ce6SGeorge Rimar while (!Error && !skip(")")) 392*481c2ce6SGeorge Rimar Script->Sections.emplace_back(OutSec, next(), Keep); 393*481c2ce6SGeorge Rimar } 394*481c2ce6SGeorge Rimar 395717677afSRui Ueyama void ScriptParser::readOutputSectionDescription() { 396e9c58065SRui Ueyama StringRef OutSec = next(); 397e9c58065SRui Ueyama Script->SectionOrder.push_back(OutSec); 3988e3b38abSDenis Protivensky expect(":"); 3998e3b38abSDenis Protivensky expect("{"); 400025d59b1SRui Ueyama while (!Error && !skip("}")) { 401*481c2ce6SGeorge Rimar StringRef Tok = next(); 402*481c2ce6SGeorge Rimar if (Tok == "*") { 403*481c2ce6SGeorge Rimar readSectionPatterns(OutSec, false); 404*481c2ce6SGeorge Rimar } else if (Tok == "KEEP") { 4058e3b38abSDenis Protivensky expect("("); 406*481c2ce6SGeorge Rimar next(); // Skip * 407*481c2ce6SGeorge Rimar readSectionPatterns(OutSec, true); 408*481c2ce6SGeorge Rimar expect(")"); 409*481c2ce6SGeorge Rimar } else { 410*481c2ce6SGeorge Rimar setError("Unknown command " + Tok); 411*481c2ce6SGeorge Rimar } 4128e3b38abSDenis Protivensky } 4138e3b38abSDenis Protivensky } 4148e3b38abSDenis Protivensky 41516b0cc9eSSimon Atanasyan static bool isUnderSysroot(StringRef Path) { 41616b0cc9eSSimon Atanasyan if (Config->Sysroot == "") 41716b0cc9eSSimon Atanasyan return false; 41816b0cc9eSSimon Atanasyan for (; !Path.empty(); Path = sys::path::parent_path(Path)) 41916b0cc9eSSimon Atanasyan if (sys::fs::equivalent(Config->Sysroot, Path)) 42016b0cc9eSSimon Atanasyan return true; 42116b0cc9eSSimon Atanasyan return false; 42216b0cc9eSSimon Atanasyan } 42316b0cc9eSSimon Atanasyan 424f7c5fbb1SRui Ueyama // Entry point. The other functions or classes are private to this file. 425f9de0d69SRui Ueyama void LinkerScript::read(MemoryBufferRef MB) { 42616b0cc9eSSimon Atanasyan StringRef Path = MB.getBufferIdentifier(); 427f9de0d69SRui Ueyama ScriptParser(&Alloc, MB.getBuffer(), isUnderSysroot(Path)).run(); 428f7c5fbb1SRui Ueyama } 4291ebc8ed7SRui Ueyama 4301ebc8ed7SRui Ueyama template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF32LE> *); 4311ebc8ed7SRui Ueyama template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF32BE> *); 4321ebc8ed7SRui Ueyama template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF64LE> *); 4331ebc8ed7SRui Ueyama template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF64BE> *); 4341ebc8ed7SRui Ueyama 4351ebc8ed7SRui Ueyama template bool LinkerScript::isDiscarded(InputSectionBase<ELF32LE> *); 4361ebc8ed7SRui Ueyama template bool LinkerScript::isDiscarded(InputSectionBase<ELF32BE> *); 4371ebc8ed7SRui Ueyama template bool LinkerScript::isDiscarded(InputSectionBase<ELF64LE> *); 4381ebc8ed7SRui Ueyama template bool LinkerScript::isDiscarded(InputSectionBase<ELF64BE> *); 4391ebc8ed7SRui Ueyama 440*481c2ce6SGeorge Rimar template bool LinkerScript::shouldKeep(InputSectionBase<ELF32LE> *); 441*481c2ce6SGeorge Rimar template bool LinkerScript::shouldKeep(InputSectionBase<ELF32BE> *); 442*481c2ce6SGeorge Rimar template bool LinkerScript::shouldKeep(InputSectionBase<ELF64LE> *); 443*481c2ce6SGeorge Rimar template bool LinkerScript::shouldKeep(InputSectionBase<ELF64BE> *); 444*481c2ce6SGeorge Rimar 4451ebc8ed7SRui Ueyama template bool SectionRule::match(InputSectionBase<ELF32LE> *); 4461ebc8ed7SRui Ueyama template bool SectionRule::match(InputSectionBase<ELF32BE> *); 4471ebc8ed7SRui Ueyama template bool SectionRule::match(InputSectionBase<ELF64LE> *); 4481ebc8ed7SRui Ueyama template bool SectionRule::match(InputSectionBase<ELF64BE> *); 449