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