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