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 
57*e2ee72b5SGeorge Rimar ArrayRef<uint8_t> LinkerScript::getFiller(StringRef Name) {
58*e2ee72b5SGeorge Rimar   for (OutSection &C : OutSections)
59*e2ee72b5SGeorge Rimar     if (C.Name == Name)
60*e2ee72b5SGeorge Rimar       return C.Filler;
61*e2ee72b5SGeorge Rimar   return {};
62*e2ee72b5SGeorge Rimar }
63*e2ee72b5SGeorge Rimar 
64e9c58065SRui Ueyama // A compartor to sort output sections. Returns -1 or 1 if both
65e9c58065SRui Ueyama // A and B are mentioned in linker scripts. Otherwise, returns 0
66e9c58065SRui Ueyama // to use the default rule which is implemented in Writer.cpp.
67717677afSRui Ueyama int LinkerScript::compareSections(StringRef A, StringRef B) {
68*e2ee72b5SGeorge Rimar   auto E = OutSections.end();
69*e2ee72b5SGeorge Rimar   auto I = std::find_if(OutSections.begin(), E,
70*e2ee72b5SGeorge Rimar                         [&](OutSection &C) { return C.Name == A; });
71*e2ee72b5SGeorge Rimar   auto J = std::find_if(OutSections.begin(), E,
72*e2ee72b5SGeorge Rimar                         [&](OutSection &C) { return C.Name == B; });
73e9c58065SRui Ueyama   if (I == E || J == E)
74717677afSRui Ueyama     return 0;
75717677afSRui Ueyama   return I < J ? -1 : 1;
76717677afSRui Ueyama }
77717677afSRui Ueyama 
78cb2aeb66SGeorge Rimar // Returns true if S matches T. S can contain glob meta-characters.
79cb2aeb66SGeorge Rimar // The asterisk ('*') matches zero or more characacters, and the question
80cb2aeb66SGeorge Rimar // mark ('?') matches one character.
811ebc8ed7SRui Ueyama static bool matchStr(StringRef S, StringRef T) {
821ebc8ed7SRui Ueyama   for (;;) {
831ebc8ed7SRui Ueyama     if (S.empty())
841ebc8ed7SRui Ueyama       return T.empty();
851ebc8ed7SRui Ueyama     if (S[0] == '*') {
861ebc8ed7SRui Ueyama       S = S.substr(1);
871ebc8ed7SRui Ueyama       if (S.empty())
881ebc8ed7SRui Ueyama         // Fast path. If a pattern is '*', it matches anything.
891ebc8ed7SRui Ueyama         return true;
901ebc8ed7SRui Ueyama       for (size_t I = 0, E = T.size(); I < E; ++I)
911ebc8ed7SRui Ueyama         if (matchStr(S, T.substr(I)))
921ebc8ed7SRui Ueyama           return true;
931ebc8ed7SRui Ueyama       return false;
941ebc8ed7SRui Ueyama     }
95cb2aeb66SGeorge Rimar     if (T.empty() || (S[0] != T[0] && S[0] != '?'))
961ebc8ed7SRui Ueyama       return false;
971ebc8ed7SRui Ueyama     S = S.substr(1);
981ebc8ed7SRui Ueyama     T = T.substr(1);
991ebc8ed7SRui Ueyama   }
1001ebc8ed7SRui Ueyama }
1011ebc8ed7SRui Ueyama 
1021ebc8ed7SRui Ueyama template <class ELFT> bool SectionRule::match(InputSectionBase<ELFT> *S) {
1031ebc8ed7SRui Ueyama   return matchStr(SectionPattern, S->getSectionName());
1041ebc8ed7SRui Ueyama }
1051ebc8ed7SRui Ueyama 
106717677afSRui Ueyama class elf2::ScriptParser {
107c3794e58SGeorge Rimar   typedef void (ScriptParser::*Handler)();
108c3794e58SGeorge Rimar 
109f7c5fbb1SRui Ueyama public:
110717677afSRui Ueyama   ScriptParser(BumpPtrAllocator *A, StringRef S, bool B)
111c3794e58SGeorge Rimar       : Saver(*A), Tokens(tokenize(S)), IsUnderSysroot(B) {}
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();
121*e2ee72b5SGeorge Rimar   StringRef peek();
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();
132c3794e58SGeorge Rimar   void readNothing() {}
133ee59282bSRui Ueyama   void readOutput();
1349159ce93SDavide Italiano   void readOutputArch();
135f7c5fbb1SRui Ueyama   void readOutputFormat();
13668a39a65SDavide Italiano   void readSearchDir();
1378e3b38abSDenis Protivensky   void readSections();
1388e3b38abSDenis Protivensky 
1398e3b38abSDenis Protivensky   void readOutputSectionDescription();
140481c2ce6SGeorge Rimar   void readSectionPatterns(StringRef OutSec, bool Keep);
141f7c5fbb1SRui Ueyama 
142*e2ee72b5SGeorge Rimar   std::vector<uint8_t> parseHex(StringRef S);
143*e2ee72b5SGeorge Rimar 
144a47ee68dSRui Ueyama   StringSaver Saver;
145f7c5fbb1SRui Ueyama   std::vector<StringRef> Tokens;
146c3794e58SGeorge Rimar   const static StringMap<Handler> Cmd;
147f7c5fbb1SRui Ueyama   size_t Pos = 0;
14816b0cc9eSSimon Atanasyan   bool IsUnderSysroot;
149f23b2320SGeorge Rimar   bool Error = false;
150f7c5fbb1SRui Ueyama };
151f7c5fbb1SRui Ueyama 
152c3794e58SGeorge Rimar const StringMap<elf2::ScriptParser::Handler> elf2::ScriptParser::Cmd = {
153c3794e58SGeorge Rimar     {"ENTRY", &ScriptParser::readEntry},
154c3794e58SGeorge Rimar     {"EXTERN", &ScriptParser::readExtern},
155c3794e58SGeorge Rimar     {"GROUP", &ScriptParser::readGroup},
156c3794e58SGeorge Rimar     {"INCLUDE", &ScriptParser::readInclude},
157c3794e58SGeorge Rimar     {"INPUT", &ScriptParser::readGroup},
158c3794e58SGeorge Rimar     {"OUTPUT", &ScriptParser::readOutput},
159c3794e58SGeorge Rimar     {"OUTPUT_ARCH", &ScriptParser::readOutputArch},
160c3794e58SGeorge Rimar     {"OUTPUT_FORMAT", &ScriptParser::readOutputFormat},
161c3794e58SGeorge Rimar     {"SEARCH_DIR", &ScriptParser::readSearchDir},
162c3794e58SGeorge Rimar     {"SECTIONS", &ScriptParser::readSections},
163c3794e58SGeorge Rimar     {";", &ScriptParser::readNothing}};
164c3794e58SGeorge Rimar 
165717677afSRui Ueyama void ScriptParser::run() {
166f7c5fbb1SRui Ueyama   while (!atEOF()) {
167f7c5fbb1SRui Ueyama     StringRef Tok = next();
168c3794e58SGeorge Rimar     if (Handler Fn = Cmd.lookup(Tok))
169c3794e58SGeorge Rimar       (this->*Fn)();
170c3794e58SGeorge Rimar     else
171025d59b1SRui Ueyama       setError("unknown directive: " + Tok);
172f7c5fbb1SRui Ueyama   }
173f7c5fbb1SRui Ueyama }
174f7c5fbb1SRui Ueyama 
175025d59b1SRui Ueyama // We don't want to record cascading errors. Keep only the first one.
176717677afSRui Ueyama void ScriptParser::setError(const Twine &Msg) {
177025d59b1SRui Ueyama   if (Error)
178025d59b1SRui Ueyama     return;
179025d59b1SRui Ueyama   error(Msg);
180025d59b1SRui Ueyama   Error = true;
181025d59b1SRui Ueyama }
182025d59b1SRui Ueyama 
183f7c5fbb1SRui Ueyama // Split S into linker script tokens.
184717677afSRui Ueyama std::vector<StringRef> ScriptParser::tokenize(StringRef S) {
185f7c5fbb1SRui Ueyama   std::vector<StringRef> Ret;
186f7c5fbb1SRui Ueyama   for (;;) {
187f7c5fbb1SRui Ueyama     S = skipSpace(S);
188f7c5fbb1SRui Ueyama     if (S.empty())
189f7c5fbb1SRui Ueyama       return Ret;
190f7c5fbb1SRui Ueyama 
191f7c5fbb1SRui Ueyama     // Quoted token
192f7c5fbb1SRui Ueyama     if (S.startswith("\"")) {
193f7c5fbb1SRui Ueyama       size_t E = S.find("\"", 1);
194025d59b1SRui Ueyama       if (E == StringRef::npos) {
195025d59b1SRui Ueyama         error("unclosed quote");
196025d59b1SRui Ueyama         return {};
197025d59b1SRui Ueyama       }
19860259337SPete Cooper       Ret.push_back(S.substr(1, E - 1));
199f7c5fbb1SRui Ueyama       S = S.substr(E + 1);
200f7c5fbb1SRui Ueyama       continue;
201f7c5fbb1SRui Ueyama     }
202f7c5fbb1SRui Ueyama 
203f7c5fbb1SRui Ueyama     // Unquoted token
204f7c5fbb1SRui Ueyama     size_t Pos = S.find_first_not_of(
205f7c5fbb1SRui Ueyama         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
206f7c5fbb1SRui Ueyama         "0123456789_.$/\\~=+[]*?-:");
207f7c5fbb1SRui Ueyama     // A character that cannot start a word (which is usually a
208f7c5fbb1SRui Ueyama     // punctuation) forms a single character token.
209f7c5fbb1SRui Ueyama     if (Pos == 0)
210f7c5fbb1SRui Ueyama       Pos = 1;
211f7c5fbb1SRui Ueyama     Ret.push_back(S.substr(0, Pos));
212f7c5fbb1SRui Ueyama     S = S.substr(Pos);
213f7c5fbb1SRui Ueyama   }
214f7c5fbb1SRui Ueyama }
215f7c5fbb1SRui Ueyama 
216f7c5fbb1SRui Ueyama // Skip leading whitespace characters or /**/-style comments.
217717677afSRui Ueyama StringRef ScriptParser::skipSpace(StringRef S) {
218f7c5fbb1SRui Ueyama   for (;;) {
219f7c5fbb1SRui Ueyama     if (S.startswith("/*")) {
220f7c5fbb1SRui Ueyama       size_t E = S.find("*/", 2);
221025d59b1SRui Ueyama       if (E == StringRef::npos) {
222025d59b1SRui Ueyama         error("unclosed comment in a linker script");
223025d59b1SRui Ueyama         return "";
224025d59b1SRui Ueyama       }
225f7c5fbb1SRui Ueyama       S = S.substr(E + 2);
226f7c5fbb1SRui Ueyama       continue;
227f7c5fbb1SRui Ueyama     }
228f7c5fbb1SRui Ueyama     size_t Size = S.size();
229f7c5fbb1SRui Ueyama     S = S.ltrim();
230f7c5fbb1SRui Ueyama     if (S.size() == Size)
231f7c5fbb1SRui Ueyama       return S;
232f7c5fbb1SRui Ueyama   }
233f7c5fbb1SRui Ueyama }
234f7c5fbb1SRui Ueyama 
235025d59b1SRui Ueyama // An errneous token is handled as if it were the last token before EOF.
236717677afSRui Ueyama bool ScriptParser::atEOF() { return Error || Tokens.size() == Pos; }
237025d59b1SRui Ueyama 
238717677afSRui Ueyama StringRef ScriptParser::next() {
239025d59b1SRui Ueyama   if (Error)
240025d59b1SRui Ueyama     return "";
241025d59b1SRui Ueyama   if (atEOF()) {
242025d59b1SRui Ueyama     setError("unexpected EOF");
243025d59b1SRui Ueyama     return "";
244025d59b1SRui Ueyama   }
245f7c5fbb1SRui Ueyama   return Tokens[Pos++];
246f7c5fbb1SRui Ueyama }
247f7c5fbb1SRui Ueyama 
248*e2ee72b5SGeorge Rimar StringRef ScriptParser::peek() {
249*e2ee72b5SGeorge Rimar   StringRef Tok = next();
250*e2ee72b5SGeorge Rimar   if (Error)
251*e2ee72b5SGeorge Rimar     return "";
252*e2ee72b5SGeorge Rimar   --Pos;
253*e2ee72b5SGeorge Rimar   return Tok;
254*e2ee72b5SGeorge Rimar }
255*e2ee72b5SGeorge Rimar 
256717677afSRui Ueyama bool ScriptParser::skip(StringRef Tok) {
257025d59b1SRui Ueyama   if (Error)
258025d59b1SRui Ueyama     return false;
259025d59b1SRui Ueyama   if (atEOF()) {
260025d59b1SRui Ueyama     setError("unexpected EOF");
261025d59b1SRui Ueyama     return false;
262025d59b1SRui Ueyama   }
2638e3b38abSDenis Protivensky   if (Tok != Tokens[Pos])
2648e3b38abSDenis Protivensky     return false;
2658e3b38abSDenis Protivensky   ++Pos;
2668e3b38abSDenis Protivensky   return true;
2678e3b38abSDenis Protivensky }
2688e3b38abSDenis Protivensky 
269717677afSRui Ueyama void ScriptParser::expect(StringRef Expect) {
270025d59b1SRui Ueyama   if (Error)
271025d59b1SRui Ueyama     return;
272f7c5fbb1SRui Ueyama   StringRef Tok = next();
273f7c5fbb1SRui Ueyama   if (Tok != Expect)
274025d59b1SRui Ueyama     setError(Expect + " expected, but got " + Tok);
275f7c5fbb1SRui Ueyama }
276f7c5fbb1SRui Ueyama 
277717677afSRui Ueyama void ScriptParser::addFile(StringRef S) {
27816b0cc9eSSimon Atanasyan   if (IsUnderSysroot && S.startswith("/")) {
27916b0cc9eSSimon Atanasyan     SmallString<128> Path;
28016b0cc9eSSimon Atanasyan     (Config->Sysroot + S).toStringRef(Path);
28116b0cc9eSSimon Atanasyan     if (sys::fs::exists(Path)) {
28216b0cc9eSSimon Atanasyan       Driver->addFile(Saver.save(Path.str()));
28316b0cc9eSSimon Atanasyan       return;
28416b0cc9eSSimon Atanasyan     }
28516b0cc9eSSimon Atanasyan   }
28616b0cc9eSSimon Atanasyan 
287f03f3cc1SRui Ueyama   if (sys::path::is_absolute(S)) {
28852a1509eSRui Ueyama     Driver->addFile(S);
28952a1509eSRui Ueyama   } else if (S.startswith("=")) {
29052a1509eSRui Ueyama     if (Config->Sysroot.empty())
29152a1509eSRui Ueyama       Driver->addFile(S.substr(1));
29252a1509eSRui Ueyama     else
29352a1509eSRui Ueyama       Driver->addFile(Saver.save(Config->Sysroot + "/" + S.substr(1)));
29452a1509eSRui Ueyama   } else if (S.startswith("-l")) {
29521eecb4fSRui Ueyama     Driver->addLibrary(S.substr(2));
296a1b8fc3bSSimon Atanasyan   } else if (sys::fs::exists(S)) {
297a1b8fc3bSSimon Atanasyan     Driver->addFile(S);
29852a1509eSRui Ueyama   } else {
29952a1509eSRui Ueyama     std::string Path = findFromSearchPaths(S);
30052a1509eSRui Ueyama     if (Path.empty())
301025d59b1SRui Ueyama       setError("Unable to find " + S);
302025d59b1SRui Ueyama     else
30352a1509eSRui Ueyama       Driver->addFile(Saver.save(Path));
30452a1509eSRui Ueyama   }
30552a1509eSRui Ueyama }
30652a1509eSRui Ueyama 
307717677afSRui Ueyama void ScriptParser::readAsNeeded() {
308f7c5fbb1SRui Ueyama   expect("(");
30935da9b6eSRui Ueyama   bool Orig = Config->AsNeeded;
31035da9b6eSRui Ueyama   Config->AsNeeded = true;
311025d59b1SRui Ueyama   while (!Error) {
312f7c5fbb1SRui Ueyama     StringRef Tok = next();
313f7c5fbb1SRui Ueyama     if (Tok == ")")
31435da9b6eSRui Ueyama       break;
31552a1509eSRui Ueyama     addFile(Tok);
316f7c5fbb1SRui Ueyama   }
31735da9b6eSRui Ueyama   Config->AsNeeded = Orig;
318f7c5fbb1SRui Ueyama }
319f7c5fbb1SRui Ueyama 
320717677afSRui Ueyama void ScriptParser::readEntry() {
32190c5099eSDenis Protivensky   // -e <symbol> takes predecence over ENTRY(<symbol>).
32290c5099eSDenis Protivensky   expect("(");
32390c5099eSDenis Protivensky   StringRef Tok = next();
32490c5099eSDenis Protivensky   if (Config->Entry.empty())
32590c5099eSDenis Protivensky     Config->Entry = Tok;
32690c5099eSDenis Protivensky   expect(")");
32790c5099eSDenis Protivensky }
32890c5099eSDenis Protivensky 
329717677afSRui Ueyama void ScriptParser::readExtern() {
33083f406cfSGeorge Rimar   expect("(");
331025d59b1SRui Ueyama   while (!Error) {
33283f406cfSGeorge Rimar     StringRef Tok = next();
33383f406cfSGeorge Rimar     if (Tok == ")")
33483f406cfSGeorge Rimar       return;
33583f406cfSGeorge Rimar     Config->Undefined.push_back(Tok);
33683f406cfSGeorge Rimar   }
33783f406cfSGeorge Rimar }
33883f406cfSGeorge Rimar 
339717677afSRui Ueyama void ScriptParser::readGroup() {
340f7c5fbb1SRui Ueyama   expect("(");
341025d59b1SRui Ueyama   while (!Error) {
342f7c5fbb1SRui Ueyama     StringRef Tok = next();
343f7c5fbb1SRui Ueyama     if (Tok == ")")
344f7c5fbb1SRui Ueyama       return;
345f7c5fbb1SRui Ueyama     if (Tok == "AS_NEEDED") {
346f7c5fbb1SRui Ueyama       readAsNeeded();
347f7c5fbb1SRui Ueyama       continue;
348f7c5fbb1SRui Ueyama     }
34952a1509eSRui Ueyama     addFile(Tok);
350f7c5fbb1SRui Ueyama   }
351f7c5fbb1SRui Ueyama }
352f7c5fbb1SRui Ueyama 
353717677afSRui Ueyama void ScriptParser::readInclude() {
35431aa1f83SRui Ueyama   StringRef Tok = next();
35531aa1f83SRui Ueyama   auto MBOrErr = MemoryBuffer::getFile(Tok);
356025d59b1SRui Ueyama   if (!MBOrErr) {
357025d59b1SRui Ueyama     setError("cannot open " + Tok);
358025d59b1SRui Ueyama     return;
359025d59b1SRui Ueyama   }
36031aa1f83SRui Ueyama   std::unique_ptr<MemoryBuffer> &MB = *MBOrErr;
361a47ee68dSRui Ueyama   StringRef S = Saver.save(MB->getMemBufferRef().getBuffer());
362a47ee68dSRui Ueyama   std::vector<StringRef> V = tokenize(S);
36331aa1f83SRui Ueyama   Tokens.insert(Tokens.begin() + Pos, V.begin(), V.end());
36431aa1f83SRui Ueyama }
36531aa1f83SRui Ueyama 
366717677afSRui Ueyama void ScriptParser::readOutput() {
367ee59282bSRui Ueyama   // -o <file> takes predecence over OUTPUT(<file>).
368ee59282bSRui Ueyama   expect("(");
369ee59282bSRui Ueyama   StringRef Tok = next();
370ee59282bSRui Ueyama   if (Config->OutputFile.empty())
371ee59282bSRui Ueyama     Config->OutputFile = Tok;
372ee59282bSRui Ueyama   expect(")");
373ee59282bSRui Ueyama }
374ee59282bSRui Ueyama 
375717677afSRui Ueyama void ScriptParser::readOutputArch() {
3769159ce93SDavide Italiano   // Error checking only for now.
3779159ce93SDavide Italiano   expect("(");
3789159ce93SDavide Italiano   next();
3799159ce93SDavide Italiano   expect(")");
3809159ce93SDavide Italiano }
3819159ce93SDavide Italiano 
382717677afSRui Ueyama void ScriptParser::readOutputFormat() {
383f7c5fbb1SRui Ueyama   // Error checking only for now.
384f7c5fbb1SRui Ueyama   expect("(");
385f7c5fbb1SRui Ueyama   next();
3866836c618SDavide Italiano   StringRef Tok = next();
3876836c618SDavide Italiano   if (Tok == ")")
3886836c618SDavide Italiano    return;
389025d59b1SRui Ueyama   if (Tok != ",") {
390025d59b1SRui Ueyama     setError("unexpected token: " + Tok);
391025d59b1SRui Ueyama     return;
392025d59b1SRui Ueyama   }
3936836c618SDavide Italiano   next();
3946836c618SDavide Italiano   expect(",");
3956836c618SDavide Italiano   next();
396f7c5fbb1SRui Ueyama   expect(")");
397f7c5fbb1SRui Ueyama }
398f7c5fbb1SRui Ueyama 
399717677afSRui Ueyama void ScriptParser::readSearchDir() {
40068a39a65SDavide Italiano   expect("(");
40152a1509eSRui Ueyama   Config->SearchPaths.push_back(next());
40268a39a65SDavide Italiano   expect(")");
40368a39a65SDavide Italiano }
40468a39a65SDavide Italiano 
405717677afSRui Ueyama void ScriptParser::readSections() {
4068e3b38abSDenis Protivensky   expect("{");
407025d59b1SRui Ueyama   while (!Error && !skip("}"))
4088e3b38abSDenis Protivensky     readOutputSectionDescription();
4098e3b38abSDenis Protivensky }
4108e3b38abSDenis Protivensky 
411481c2ce6SGeorge Rimar void ScriptParser::readSectionPatterns(StringRef OutSec, bool Keep) {
412481c2ce6SGeorge Rimar   expect("(");
413481c2ce6SGeorge Rimar   while (!Error && !skip(")"))
414481c2ce6SGeorge Rimar     Script->Sections.emplace_back(OutSec, next(), Keep);
415481c2ce6SGeorge Rimar }
416481c2ce6SGeorge Rimar 
417*e2ee72b5SGeorge Rimar std::vector<uint8_t> ScriptParser::parseHex(StringRef S) {
418*e2ee72b5SGeorge Rimar   std::vector<uint8_t> Hex;
419*e2ee72b5SGeorge Rimar   while (!S.empty()) {
420*e2ee72b5SGeorge Rimar     StringRef B = S.substr(0, 2);
421*e2ee72b5SGeorge Rimar     S = S.substr(2);
422*e2ee72b5SGeorge Rimar     uint8_t H;
423*e2ee72b5SGeorge Rimar     if (B.getAsInteger(16, H)) {
424*e2ee72b5SGeorge Rimar       setError("Not a HEX value: " + B);
425*e2ee72b5SGeorge Rimar       return {};
426*e2ee72b5SGeorge Rimar     }
427*e2ee72b5SGeorge Rimar     Hex.push_back(H);
428*e2ee72b5SGeorge Rimar   }
429*e2ee72b5SGeorge Rimar   return Hex;
430*e2ee72b5SGeorge Rimar }
431*e2ee72b5SGeorge Rimar 
432717677afSRui Ueyama void ScriptParser::readOutputSectionDescription() {
433*e2ee72b5SGeorge Rimar   OutSection OutSec;
434*e2ee72b5SGeorge Rimar   OutSec.Name = next();
4358e3b38abSDenis Protivensky   expect(":");
4368e3b38abSDenis Protivensky   expect("{");
437025d59b1SRui Ueyama   while (!Error && !skip("}")) {
438481c2ce6SGeorge Rimar     StringRef Tok = next();
439481c2ce6SGeorge Rimar     if (Tok == "*") {
440*e2ee72b5SGeorge Rimar       readSectionPatterns(OutSec.Name, false);
441481c2ce6SGeorge Rimar     } else if (Tok == "KEEP") {
4428e3b38abSDenis Protivensky       expect("(");
443481c2ce6SGeorge Rimar       next(); // Skip *
444*e2ee72b5SGeorge Rimar       readSectionPatterns(OutSec.Name, true);
445481c2ce6SGeorge Rimar       expect(")");
446481c2ce6SGeorge Rimar     } else {
447481c2ce6SGeorge Rimar       setError("Unknown command " + Tok);
448481c2ce6SGeorge Rimar     }
4498e3b38abSDenis Protivensky   }
450*e2ee72b5SGeorge Rimar   StringRef Tok = peek();
451*e2ee72b5SGeorge Rimar   if (Tok.startswith("=")) {
452*e2ee72b5SGeorge Rimar     if (!Tok.startswith("=0x")) {
453*e2ee72b5SGeorge Rimar       setError("Filler should be a HEX value");
454*e2ee72b5SGeorge Rimar       return;
455*e2ee72b5SGeorge Rimar     }
456*e2ee72b5SGeorge Rimar     Tok = Tok.substr(3); // Skip '=0x'
457*e2ee72b5SGeorge Rimar     OutSec.Filler = parseHex(Tok);
458*e2ee72b5SGeorge Rimar     next();
459*e2ee72b5SGeorge Rimar   }
460*e2ee72b5SGeorge Rimar   Script->OutSections.push_back(OutSec);
4618e3b38abSDenis Protivensky }
4628e3b38abSDenis Protivensky 
46316b0cc9eSSimon Atanasyan static bool isUnderSysroot(StringRef Path) {
46416b0cc9eSSimon Atanasyan   if (Config->Sysroot == "")
46516b0cc9eSSimon Atanasyan     return false;
46616b0cc9eSSimon Atanasyan   for (; !Path.empty(); Path = sys::path::parent_path(Path))
46716b0cc9eSSimon Atanasyan     if (sys::fs::equivalent(Config->Sysroot, Path))
46816b0cc9eSSimon Atanasyan       return true;
46916b0cc9eSSimon Atanasyan   return false;
47016b0cc9eSSimon Atanasyan }
47116b0cc9eSSimon Atanasyan 
472f7c5fbb1SRui Ueyama // Entry point. The other functions or classes are private to this file.
473f9de0d69SRui Ueyama void LinkerScript::read(MemoryBufferRef MB) {
47416b0cc9eSSimon Atanasyan   StringRef Path = MB.getBufferIdentifier();
475f9de0d69SRui Ueyama   ScriptParser(&Alloc, MB.getBuffer(), isUnderSysroot(Path)).run();
476f7c5fbb1SRui Ueyama }
4771ebc8ed7SRui Ueyama 
4781ebc8ed7SRui Ueyama template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF32LE> *);
4791ebc8ed7SRui Ueyama template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF32BE> *);
4801ebc8ed7SRui Ueyama template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF64LE> *);
4811ebc8ed7SRui Ueyama template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF64BE> *);
4821ebc8ed7SRui Ueyama 
4831ebc8ed7SRui Ueyama template bool LinkerScript::isDiscarded(InputSectionBase<ELF32LE> *);
4841ebc8ed7SRui Ueyama template bool LinkerScript::isDiscarded(InputSectionBase<ELF32BE> *);
4851ebc8ed7SRui Ueyama template bool LinkerScript::isDiscarded(InputSectionBase<ELF64LE> *);
4861ebc8ed7SRui Ueyama template bool LinkerScript::isDiscarded(InputSectionBase<ELF64BE> *);
4871ebc8ed7SRui Ueyama 
488481c2ce6SGeorge Rimar template bool LinkerScript::shouldKeep(InputSectionBase<ELF32LE> *);
489481c2ce6SGeorge Rimar template bool LinkerScript::shouldKeep(InputSectionBase<ELF32BE> *);
490481c2ce6SGeorge Rimar template bool LinkerScript::shouldKeep(InputSectionBase<ELF64LE> *);
491481c2ce6SGeorge Rimar template bool LinkerScript::shouldKeep(InputSectionBase<ELF64BE> *);
492