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> 34481c2ce6SGeorge Rimar SectionRule *LinkerScript::find(InputSectionBase<ELFT> *S) { 351ebc8ed7SRui Ueyama for (SectionRule &R : Sections) 361ebc8ed7SRui Ueyama if (R.match(S)) 37481c2ce6SGeorge Rimar return &R; 38481c2ce6SGeorge Rimar return nullptr; 39481c2ce6SGeorge Rimar } 40481c2ce6SGeorge Rimar 41481c2ce6SGeorge Rimar template <class ELFT> 42481c2ce6SGeorge Rimar StringRef LinkerScript::getOutputSection(InputSectionBase<ELFT> *S) { 43481c2ce6SGeorge Rimar SectionRule *R = find(S); 44481c2ce6SGeorge 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 52481c2ce6SGeorge Rimar template <class ELFT> bool LinkerScript::shouldKeep(InputSectionBase<ELFT> *S) { 53481c2ce6SGeorge Rimar SectionRule *R = find(S); 54481c2ce6SGeorge Rimar return R && R->Keep; 55481c2ce6SGeorge Rimar } 56481c2ce6SGeorge 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 69*cb2aeb66SGeorge Rimar // Returns true if S matches T. S can contain glob meta-characters. 70*cb2aeb66SGeorge Rimar // The asterisk ('*') matches zero or more characacters, and the question 71*cb2aeb66SGeorge Rimar // mark ('?') matches one character. 721ebc8ed7SRui Ueyama static bool matchStr(StringRef S, StringRef T) { 731ebc8ed7SRui Ueyama for (;;) { 741ebc8ed7SRui Ueyama if (S.empty()) 751ebc8ed7SRui Ueyama return T.empty(); 761ebc8ed7SRui Ueyama if (S[0] == '*') { 771ebc8ed7SRui Ueyama S = S.substr(1); 781ebc8ed7SRui Ueyama if (S.empty()) 791ebc8ed7SRui Ueyama // Fast path. If a pattern is '*', it matches anything. 801ebc8ed7SRui Ueyama return true; 811ebc8ed7SRui Ueyama for (size_t I = 0, E = T.size(); I < E; ++I) 821ebc8ed7SRui Ueyama if (matchStr(S, T.substr(I))) 831ebc8ed7SRui Ueyama return true; 841ebc8ed7SRui Ueyama return false; 851ebc8ed7SRui Ueyama } 86*cb2aeb66SGeorge Rimar if (T.empty() || (S[0] != T[0] && S[0] != '?')) 871ebc8ed7SRui Ueyama return false; 881ebc8ed7SRui Ueyama S = S.substr(1); 891ebc8ed7SRui Ueyama T = T.substr(1); 901ebc8ed7SRui Ueyama } 911ebc8ed7SRui Ueyama } 921ebc8ed7SRui Ueyama 931ebc8ed7SRui Ueyama template <class ELFT> bool SectionRule::match(InputSectionBase<ELFT> *S) { 941ebc8ed7SRui Ueyama return matchStr(SectionPattern, S->getSectionName()); 951ebc8ed7SRui Ueyama } 961ebc8ed7SRui Ueyama 97717677afSRui Ueyama class elf2::ScriptParser { 98f7c5fbb1SRui Ueyama public: 99717677afSRui Ueyama ScriptParser(BumpPtrAllocator *A, StringRef S, bool B) 100f23b2320SGeorge Rimar : Saver(*A), Tokens(tokenize(S)), IsUnderSysroot(B) { 101d2389bfdSGeorge Rimar Cmd["ENTRY"] = std::mem_fn(&ScriptParser::readEntry); 102d2389bfdSGeorge Rimar Cmd["EXTERN"] = std::mem_fn(&ScriptParser::readExtern); 103d2389bfdSGeorge Rimar Cmd["GROUP"] = std::mem_fn(&ScriptParser::readGroup); 104d2389bfdSGeorge Rimar Cmd["INCLUDE"] = std::mem_fn(&ScriptParser::readInclude); 105d2389bfdSGeorge Rimar Cmd["INPUT"] = std::mem_fn(&ScriptParser::readGroup); 106d2389bfdSGeorge Rimar Cmd["OUTPUT"] = std::mem_fn(&ScriptParser::readOutput); 107d2389bfdSGeorge Rimar Cmd["OUTPUT_ARCH"] = std::mem_fn(&ScriptParser::readOutputArch); 108d2389bfdSGeorge Rimar Cmd["OUTPUT_FORMAT"] = std::mem_fn(&ScriptParser::readOutputFormat); 109d2389bfdSGeorge Rimar Cmd["SEARCH_DIR"] = std::mem_fn(&ScriptParser::readSearchDir); 110d2389bfdSGeorge Rimar Cmd["SECTIONS"] = std::mem_fn(&ScriptParser::readSections); 111f23b2320SGeorge Rimar Cmd[";"] = [](ScriptParser &) {}; 112f23b2320SGeorge Rimar } 113f23b2320SGeorge Rimar 114f7c5fbb1SRui Ueyama void run(); 115f7c5fbb1SRui Ueyama 116f7c5fbb1SRui Ueyama private: 117025d59b1SRui Ueyama void setError(const Twine &Msg); 118f7c5fbb1SRui Ueyama static std::vector<StringRef> tokenize(StringRef S); 119f7c5fbb1SRui Ueyama static StringRef skipSpace(StringRef S); 120025d59b1SRui Ueyama bool atEOF(); 121f7c5fbb1SRui Ueyama StringRef next(); 1228e3b38abSDenis Protivensky bool skip(StringRef Tok); 123f7c5fbb1SRui Ueyama void expect(StringRef Expect); 124f7c5fbb1SRui Ueyama 12552a1509eSRui Ueyama void addFile(StringRef Path); 12652a1509eSRui Ueyama 127f7c5fbb1SRui Ueyama void readAsNeeded(); 12890c5099eSDenis Protivensky void readEntry(); 12983f406cfSGeorge Rimar void readExtern(); 130f7c5fbb1SRui Ueyama void readGroup(); 13131aa1f83SRui Ueyama void readInclude(); 132ee59282bSRui Ueyama void readOutput(); 1339159ce93SDavide Italiano void readOutputArch(); 134f7c5fbb1SRui Ueyama void readOutputFormat(); 13568a39a65SDavide Italiano void readSearchDir(); 1368e3b38abSDenis Protivensky void readSections(); 1378e3b38abSDenis Protivensky 1388e3b38abSDenis Protivensky void readOutputSectionDescription(); 139481c2ce6SGeorge Rimar void readSectionPatterns(StringRef OutSec, bool Keep); 140f7c5fbb1SRui Ueyama 141a47ee68dSRui Ueyama StringSaver Saver; 142f7c5fbb1SRui Ueyama std::vector<StringRef> Tokens; 143f23b2320SGeorge Rimar llvm::StringMap<std::function<void(ScriptParser &)>> Cmd; 144f7c5fbb1SRui Ueyama size_t Pos = 0; 14516b0cc9eSSimon Atanasyan bool IsUnderSysroot; 146f23b2320SGeorge Rimar bool Error = false; 147f7c5fbb1SRui Ueyama }; 148f7c5fbb1SRui Ueyama 149717677afSRui Ueyama void ScriptParser::run() { 150f7c5fbb1SRui Ueyama while (!atEOF()) { 151f7c5fbb1SRui Ueyama StringRef Tok = next(); 152f23b2320SGeorge Rimar auto It = Cmd.find(Tok); 153f23b2320SGeorge Rimar if (It != Cmd.end()) { 154f23b2320SGeorge Rimar std::function<void(ScriptParser &)> &Handler = It->second; 155f23b2320SGeorge Rimar Handler(*this); 156f7c5fbb1SRui Ueyama } else { 157025d59b1SRui Ueyama setError("unknown directive: " + Tok); 158f7c5fbb1SRui Ueyama } 159f7c5fbb1SRui Ueyama } 160f7c5fbb1SRui Ueyama } 161f7c5fbb1SRui Ueyama 162025d59b1SRui Ueyama // We don't want to record cascading errors. Keep only the first one. 163717677afSRui Ueyama void ScriptParser::setError(const Twine &Msg) { 164025d59b1SRui Ueyama if (Error) 165025d59b1SRui Ueyama return; 166025d59b1SRui Ueyama error(Msg); 167025d59b1SRui Ueyama Error = true; 168025d59b1SRui Ueyama } 169025d59b1SRui Ueyama 170f7c5fbb1SRui Ueyama // Split S into linker script tokens. 171717677afSRui Ueyama std::vector<StringRef> ScriptParser::tokenize(StringRef S) { 172f7c5fbb1SRui Ueyama std::vector<StringRef> Ret; 173f7c5fbb1SRui Ueyama for (;;) { 174f7c5fbb1SRui Ueyama S = skipSpace(S); 175f7c5fbb1SRui Ueyama if (S.empty()) 176f7c5fbb1SRui Ueyama return Ret; 177f7c5fbb1SRui Ueyama 178f7c5fbb1SRui Ueyama // Quoted token 179f7c5fbb1SRui Ueyama if (S.startswith("\"")) { 180f7c5fbb1SRui Ueyama size_t E = S.find("\"", 1); 181025d59b1SRui Ueyama if (E == StringRef::npos) { 182025d59b1SRui Ueyama error("unclosed quote"); 183025d59b1SRui Ueyama return {}; 184025d59b1SRui Ueyama } 18560259337SPete Cooper Ret.push_back(S.substr(1, E - 1)); 186f7c5fbb1SRui Ueyama S = S.substr(E + 1); 187f7c5fbb1SRui Ueyama continue; 188f7c5fbb1SRui Ueyama } 189f7c5fbb1SRui Ueyama 190f7c5fbb1SRui Ueyama // Unquoted token 191f7c5fbb1SRui Ueyama size_t Pos = S.find_first_not_of( 192f7c5fbb1SRui Ueyama "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 193f7c5fbb1SRui Ueyama "0123456789_.$/\\~=+[]*?-:"); 194f7c5fbb1SRui Ueyama // A character that cannot start a word (which is usually a 195f7c5fbb1SRui Ueyama // punctuation) forms a single character token. 196f7c5fbb1SRui Ueyama if (Pos == 0) 197f7c5fbb1SRui Ueyama Pos = 1; 198f7c5fbb1SRui Ueyama Ret.push_back(S.substr(0, Pos)); 199f7c5fbb1SRui Ueyama S = S.substr(Pos); 200f7c5fbb1SRui Ueyama } 201f7c5fbb1SRui Ueyama } 202f7c5fbb1SRui Ueyama 203f7c5fbb1SRui Ueyama // Skip leading whitespace characters or /**/-style comments. 204717677afSRui Ueyama StringRef ScriptParser::skipSpace(StringRef S) { 205f7c5fbb1SRui Ueyama for (;;) { 206f7c5fbb1SRui Ueyama if (S.startswith("/*")) { 207f7c5fbb1SRui Ueyama size_t E = S.find("*/", 2); 208025d59b1SRui Ueyama if (E == StringRef::npos) { 209025d59b1SRui Ueyama error("unclosed comment in a linker script"); 210025d59b1SRui Ueyama return ""; 211025d59b1SRui Ueyama } 212f7c5fbb1SRui Ueyama S = S.substr(E + 2); 213f7c5fbb1SRui Ueyama continue; 214f7c5fbb1SRui Ueyama } 215f7c5fbb1SRui Ueyama size_t Size = S.size(); 216f7c5fbb1SRui Ueyama S = S.ltrim(); 217f7c5fbb1SRui Ueyama if (S.size() == Size) 218f7c5fbb1SRui Ueyama return S; 219f7c5fbb1SRui Ueyama } 220f7c5fbb1SRui Ueyama } 221f7c5fbb1SRui Ueyama 222025d59b1SRui Ueyama // An errneous token is handled as if it were the last token before EOF. 223717677afSRui Ueyama bool ScriptParser::atEOF() { return Error || Tokens.size() == Pos; } 224025d59b1SRui Ueyama 225717677afSRui Ueyama StringRef ScriptParser::next() { 226025d59b1SRui Ueyama if (Error) 227025d59b1SRui Ueyama return ""; 228025d59b1SRui Ueyama if (atEOF()) { 229025d59b1SRui Ueyama setError("unexpected EOF"); 230025d59b1SRui Ueyama return ""; 231025d59b1SRui Ueyama } 232f7c5fbb1SRui Ueyama return Tokens[Pos++]; 233f7c5fbb1SRui Ueyama } 234f7c5fbb1SRui Ueyama 235717677afSRui Ueyama bool ScriptParser::skip(StringRef Tok) { 236025d59b1SRui Ueyama if (Error) 237025d59b1SRui Ueyama return false; 238025d59b1SRui Ueyama if (atEOF()) { 239025d59b1SRui Ueyama setError("unexpected EOF"); 240025d59b1SRui Ueyama return false; 241025d59b1SRui Ueyama } 2428e3b38abSDenis Protivensky if (Tok != Tokens[Pos]) 2438e3b38abSDenis Protivensky return false; 2448e3b38abSDenis Protivensky ++Pos; 2458e3b38abSDenis Protivensky return true; 2468e3b38abSDenis Protivensky } 2478e3b38abSDenis Protivensky 248717677afSRui Ueyama void ScriptParser::expect(StringRef Expect) { 249025d59b1SRui Ueyama if (Error) 250025d59b1SRui Ueyama return; 251f7c5fbb1SRui Ueyama StringRef Tok = next(); 252f7c5fbb1SRui Ueyama if (Tok != Expect) 253025d59b1SRui Ueyama setError(Expect + " expected, but got " + Tok); 254f7c5fbb1SRui Ueyama } 255f7c5fbb1SRui Ueyama 256717677afSRui Ueyama void ScriptParser::addFile(StringRef S) { 25716b0cc9eSSimon Atanasyan if (IsUnderSysroot && S.startswith("/")) { 25816b0cc9eSSimon Atanasyan SmallString<128> Path; 25916b0cc9eSSimon Atanasyan (Config->Sysroot + S).toStringRef(Path); 26016b0cc9eSSimon Atanasyan if (sys::fs::exists(Path)) { 26116b0cc9eSSimon Atanasyan Driver->addFile(Saver.save(Path.str())); 26216b0cc9eSSimon Atanasyan return; 26316b0cc9eSSimon Atanasyan } 26416b0cc9eSSimon Atanasyan } 26516b0cc9eSSimon Atanasyan 266f03f3cc1SRui Ueyama if (sys::path::is_absolute(S)) { 26752a1509eSRui Ueyama Driver->addFile(S); 26852a1509eSRui Ueyama } else if (S.startswith("=")) { 26952a1509eSRui Ueyama if (Config->Sysroot.empty()) 27052a1509eSRui Ueyama Driver->addFile(S.substr(1)); 27152a1509eSRui Ueyama else 27252a1509eSRui Ueyama Driver->addFile(Saver.save(Config->Sysroot + "/" + S.substr(1))); 27352a1509eSRui Ueyama } else if (S.startswith("-l")) { 27421eecb4fSRui Ueyama Driver->addLibrary(S.substr(2)); 275a1b8fc3bSSimon Atanasyan } else if (sys::fs::exists(S)) { 276a1b8fc3bSSimon Atanasyan Driver->addFile(S); 27752a1509eSRui Ueyama } else { 27852a1509eSRui Ueyama std::string Path = findFromSearchPaths(S); 27952a1509eSRui Ueyama if (Path.empty()) 280025d59b1SRui Ueyama setError("Unable to find " + S); 281025d59b1SRui Ueyama else 28252a1509eSRui Ueyama Driver->addFile(Saver.save(Path)); 28352a1509eSRui Ueyama } 28452a1509eSRui Ueyama } 28552a1509eSRui Ueyama 286717677afSRui Ueyama void ScriptParser::readAsNeeded() { 287f7c5fbb1SRui Ueyama expect("("); 28835da9b6eSRui Ueyama bool Orig = Config->AsNeeded; 28935da9b6eSRui Ueyama Config->AsNeeded = true; 290025d59b1SRui Ueyama while (!Error) { 291f7c5fbb1SRui Ueyama StringRef Tok = next(); 292f7c5fbb1SRui Ueyama if (Tok == ")") 29335da9b6eSRui Ueyama break; 29452a1509eSRui Ueyama addFile(Tok); 295f7c5fbb1SRui Ueyama } 29635da9b6eSRui Ueyama Config->AsNeeded = Orig; 297f7c5fbb1SRui Ueyama } 298f7c5fbb1SRui Ueyama 299717677afSRui Ueyama void ScriptParser::readEntry() { 30090c5099eSDenis Protivensky // -e <symbol> takes predecence over ENTRY(<symbol>). 30190c5099eSDenis Protivensky expect("("); 30290c5099eSDenis Protivensky StringRef Tok = next(); 30390c5099eSDenis Protivensky if (Config->Entry.empty()) 30490c5099eSDenis Protivensky Config->Entry = Tok; 30590c5099eSDenis Protivensky expect(")"); 30690c5099eSDenis Protivensky } 30790c5099eSDenis Protivensky 308717677afSRui Ueyama void ScriptParser::readExtern() { 30983f406cfSGeorge Rimar expect("("); 310025d59b1SRui Ueyama while (!Error) { 31183f406cfSGeorge Rimar StringRef Tok = next(); 31283f406cfSGeorge Rimar if (Tok == ")") 31383f406cfSGeorge Rimar return; 31483f406cfSGeorge Rimar Config->Undefined.push_back(Tok); 31583f406cfSGeorge Rimar } 31683f406cfSGeorge Rimar } 31783f406cfSGeorge Rimar 318717677afSRui Ueyama void ScriptParser::readGroup() { 319f7c5fbb1SRui Ueyama expect("("); 320025d59b1SRui Ueyama while (!Error) { 321f7c5fbb1SRui Ueyama StringRef Tok = next(); 322f7c5fbb1SRui Ueyama if (Tok == ")") 323f7c5fbb1SRui Ueyama return; 324f7c5fbb1SRui Ueyama if (Tok == "AS_NEEDED") { 325f7c5fbb1SRui Ueyama readAsNeeded(); 326f7c5fbb1SRui Ueyama continue; 327f7c5fbb1SRui Ueyama } 32852a1509eSRui Ueyama addFile(Tok); 329f7c5fbb1SRui Ueyama } 330f7c5fbb1SRui Ueyama } 331f7c5fbb1SRui Ueyama 332717677afSRui Ueyama void ScriptParser::readInclude() { 33331aa1f83SRui Ueyama StringRef Tok = next(); 33431aa1f83SRui Ueyama auto MBOrErr = MemoryBuffer::getFile(Tok); 335025d59b1SRui Ueyama if (!MBOrErr) { 336025d59b1SRui Ueyama setError("cannot open " + Tok); 337025d59b1SRui Ueyama return; 338025d59b1SRui Ueyama } 33931aa1f83SRui Ueyama std::unique_ptr<MemoryBuffer> &MB = *MBOrErr; 340a47ee68dSRui Ueyama StringRef S = Saver.save(MB->getMemBufferRef().getBuffer()); 341a47ee68dSRui Ueyama std::vector<StringRef> V = tokenize(S); 34231aa1f83SRui Ueyama Tokens.insert(Tokens.begin() + Pos, V.begin(), V.end()); 34331aa1f83SRui Ueyama } 34431aa1f83SRui Ueyama 345717677afSRui Ueyama void ScriptParser::readOutput() { 346ee59282bSRui Ueyama // -o <file> takes predecence over OUTPUT(<file>). 347ee59282bSRui Ueyama expect("("); 348ee59282bSRui Ueyama StringRef Tok = next(); 349ee59282bSRui Ueyama if (Config->OutputFile.empty()) 350ee59282bSRui Ueyama Config->OutputFile = Tok; 351ee59282bSRui Ueyama expect(")"); 352ee59282bSRui Ueyama } 353ee59282bSRui Ueyama 354717677afSRui Ueyama void ScriptParser::readOutputArch() { 3559159ce93SDavide Italiano // Error checking only for now. 3569159ce93SDavide Italiano expect("("); 3579159ce93SDavide Italiano next(); 3589159ce93SDavide Italiano expect(")"); 3599159ce93SDavide Italiano } 3609159ce93SDavide Italiano 361717677afSRui Ueyama void ScriptParser::readOutputFormat() { 362f7c5fbb1SRui Ueyama // Error checking only for now. 363f7c5fbb1SRui Ueyama expect("("); 364f7c5fbb1SRui Ueyama next(); 3656836c618SDavide Italiano StringRef Tok = next(); 3666836c618SDavide Italiano if (Tok == ")") 3676836c618SDavide Italiano return; 368025d59b1SRui Ueyama if (Tok != ",") { 369025d59b1SRui Ueyama setError("unexpected token: " + Tok); 370025d59b1SRui Ueyama return; 371025d59b1SRui Ueyama } 3726836c618SDavide Italiano next(); 3736836c618SDavide Italiano expect(","); 3746836c618SDavide Italiano next(); 375f7c5fbb1SRui Ueyama expect(")"); 376f7c5fbb1SRui Ueyama } 377f7c5fbb1SRui Ueyama 378717677afSRui Ueyama void ScriptParser::readSearchDir() { 37968a39a65SDavide Italiano expect("("); 38052a1509eSRui Ueyama Config->SearchPaths.push_back(next()); 38168a39a65SDavide Italiano expect(")"); 38268a39a65SDavide Italiano } 38368a39a65SDavide Italiano 384717677afSRui Ueyama void ScriptParser::readSections() { 3858e3b38abSDenis Protivensky expect("{"); 386025d59b1SRui Ueyama while (!Error && !skip("}")) 3878e3b38abSDenis Protivensky readOutputSectionDescription(); 3888e3b38abSDenis Protivensky } 3898e3b38abSDenis Protivensky 390481c2ce6SGeorge Rimar void ScriptParser::readSectionPatterns(StringRef OutSec, bool Keep) { 391481c2ce6SGeorge Rimar expect("("); 392481c2ce6SGeorge Rimar while (!Error && !skip(")")) 393481c2ce6SGeorge Rimar Script->Sections.emplace_back(OutSec, next(), Keep); 394481c2ce6SGeorge Rimar } 395481c2ce6SGeorge Rimar 396717677afSRui Ueyama void ScriptParser::readOutputSectionDescription() { 397e9c58065SRui Ueyama StringRef OutSec = next(); 398e9c58065SRui Ueyama Script->SectionOrder.push_back(OutSec); 3998e3b38abSDenis Protivensky expect(":"); 4008e3b38abSDenis Protivensky expect("{"); 401025d59b1SRui Ueyama while (!Error && !skip("}")) { 402481c2ce6SGeorge Rimar StringRef Tok = next(); 403481c2ce6SGeorge Rimar if (Tok == "*") { 404481c2ce6SGeorge Rimar readSectionPatterns(OutSec, false); 405481c2ce6SGeorge Rimar } else if (Tok == "KEEP") { 4068e3b38abSDenis Protivensky expect("("); 407481c2ce6SGeorge Rimar next(); // Skip * 408481c2ce6SGeorge Rimar readSectionPatterns(OutSec, true); 409481c2ce6SGeorge Rimar expect(")"); 410481c2ce6SGeorge Rimar } else { 411481c2ce6SGeorge Rimar setError("Unknown command " + Tok); 412481c2ce6SGeorge Rimar } 4138e3b38abSDenis Protivensky } 4148e3b38abSDenis Protivensky } 4158e3b38abSDenis Protivensky 41616b0cc9eSSimon Atanasyan static bool isUnderSysroot(StringRef Path) { 41716b0cc9eSSimon Atanasyan if (Config->Sysroot == "") 41816b0cc9eSSimon Atanasyan return false; 41916b0cc9eSSimon Atanasyan for (; !Path.empty(); Path = sys::path::parent_path(Path)) 42016b0cc9eSSimon Atanasyan if (sys::fs::equivalent(Config->Sysroot, Path)) 42116b0cc9eSSimon Atanasyan return true; 42216b0cc9eSSimon Atanasyan return false; 42316b0cc9eSSimon Atanasyan } 42416b0cc9eSSimon Atanasyan 425f7c5fbb1SRui Ueyama // Entry point. The other functions or classes are private to this file. 426f9de0d69SRui Ueyama void LinkerScript::read(MemoryBufferRef MB) { 42716b0cc9eSSimon Atanasyan StringRef Path = MB.getBufferIdentifier(); 428f9de0d69SRui Ueyama ScriptParser(&Alloc, MB.getBuffer(), isUnderSysroot(Path)).run(); 429f7c5fbb1SRui Ueyama } 4301ebc8ed7SRui Ueyama 4311ebc8ed7SRui Ueyama template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF32LE> *); 4321ebc8ed7SRui Ueyama template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF32BE> *); 4331ebc8ed7SRui Ueyama template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF64LE> *); 4341ebc8ed7SRui Ueyama template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF64BE> *); 4351ebc8ed7SRui Ueyama 4361ebc8ed7SRui Ueyama template bool LinkerScript::isDiscarded(InputSectionBase<ELF32LE> *); 4371ebc8ed7SRui Ueyama template bool LinkerScript::isDiscarded(InputSectionBase<ELF32BE> *); 4381ebc8ed7SRui Ueyama template bool LinkerScript::isDiscarded(InputSectionBase<ELF64LE> *); 4391ebc8ed7SRui Ueyama template bool LinkerScript::isDiscarded(InputSectionBase<ELF64BE> *); 4401ebc8ed7SRui Ueyama 441481c2ce6SGeorge Rimar template bool LinkerScript::shouldKeep(InputSectionBase<ELF32LE> *); 442481c2ce6SGeorge Rimar template bool LinkerScript::shouldKeep(InputSectionBase<ELF32BE> *); 443481c2ce6SGeorge Rimar template bool LinkerScript::shouldKeep(InputSectionBase<ELF64LE> *); 444481c2ce6SGeorge Rimar template bool LinkerScript::shouldKeep(InputSectionBase<ELF64BE> *); 445481c2ce6SGeorge Rimar 4461ebc8ed7SRui Ueyama template bool SectionRule::match(InputSectionBase<ELF32LE> *); 4471ebc8ed7SRui Ueyama template bool SectionRule::match(InputSectionBase<ELF32BE> *); 4481ebc8ed7SRui Ueyama template bool SectionRule::match(InputSectionBase<ELF64LE> *); 4491ebc8ed7SRui Ueyama template bool SectionRule::match(InputSectionBase<ELF64BE> *); 450