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"
20652852c5SGeorge Rimar #include "OutputSections.h"
21e77b5bf6SAdhemerval Zanella #include "ScriptParser.h"
22f7c5fbb1SRui Ueyama #include "SymbolTable.h"
23652852c5SGeorge Rimar #include "llvm/Support/ELF.h"
24f7c5fbb1SRui Ueyama #include "llvm/Support/FileSystem.h"
25f7c5fbb1SRui Ueyama #include "llvm/Support/MemoryBuffer.h"
26f03f3cc1SRui Ueyama #include "llvm/Support/Path.h"
27a47ee68dSRui Ueyama #include "llvm/Support/StringSaver.h"
28f7c5fbb1SRui Ueyama 
29f7c5fbb1SRui Ueyama using namespace llvm;
30652852c5SGeorge Rimar using namespace llvm::ELF;
311ebc8ed7SRui Ueyama using namespace llvm::object;
32f7c5fbb1SRui Ueyama using namespace lld;
33e0df00b9SRafael Espindola using namespace lld::elf;
34f7c5fbb1SRui Ueyama 
35e0df00b9SRafael Espindola LinkerScript *elf::Script;
36717677afSRui Ueyama 
37652852c5SGeorge Rimar static uint64_t getInteger(StringRef S) {
38652852c5SGeorge Rimar   uint64_t V;
39652852c5SGeorge Rimar   if (S.getAsInteger(0, V)) {
40652852c5SGeorge Rimar     error("malformed number: " + S);
41652852c5SGeorge Rimar     return 0;
42652852c5SGeorge Rimar   }
43652852c5SGeorge Rimar   return V;
44652852c5SGeorge Rimar }
45652852c5SGeorge Rimar 
46652852c5SGeorge Rimar // Evaluates the expression given by list of tokens.
47652852c5SGeorge Rimar uint64_t LinkerScript::evaluate(std::vector<StringRef> &Tokens,
48652852c5SGeorge Rimar                                 uint64_t LocCounter) {
49652852c5SGeorge Rimar   uint64_t Result = 0;
50652852c5SGeorge Rimar   for (size_t I = 0, E = Tokens.size(); I < E; ++I) {
51652852c5SGeorge Rimar     // Each second token should be '+' as this is the
52652852c5SGeorge Rimar     // only operator we support now.
53652852c5SGeorge Rimar     if (I % 2 == 1) {
54652852c5SGeorge Rimar       if (Tokens[I] == "+")
55652852c5SGeorge Rimar         continue;
56652852c5SGeorge Rimar       error("error in location counter expression");
57652852c5SGeorge Rimar       return 0;
58652852c5SGeorge Rimar     }
59652852c5SGeorge Rimar 
60652852c5SGeorge Rimar     StringRef Tok = Tokens[I];
61652852c5SGeorge Rimar     if (Tok == ".")
62652852c5SGeorge Rimar       Result += LocCounter;
63652852c5SGeorge Rimar     else
64652852c5SGeorge Rimar       Result += getInteger(Tok);
65652852c5SGeorge Rimar   }
66652852c5SGeorge Rimar   return Result;
67652852c5SGeorge Rimar }
68652852c5SGeorge Rimar 
691ebc8ed7SRui Ueyama template <class ELFT>
70481c2ce6SGeorge Rimar SectionRule *LinkerScript::find(InputSectionBase<ELFT> *S) {
711ebc8ed7SRui Ueyama   for (SectionRule &R : Sections)
721ebc8ed7SRui Ueyama     if (R.match(S))
73481c2ce6SGeorge Rimar       return &R;
74481c2ce6SGeorge Rimar   return nullptr;
75481c2ce6SGeorge Rimar }
76481c2ce6SGeorge Rimar 
77481c2ce6SGeorge Rimar template <class ELFT>
78481c2ce6SGeorge Rimar StringRef LinkerScript::getOutputSection(InputSectionBase<ELFT> *S) {
79481c2ce6SGeorge Rimar   SectionRule *R = find(S);
80481c2ce6SGeorge Rimar   return R ? R->Dest : "";
81717677afSRui Ueyama }
82717677afSRui Ueyama 
831ebc8ed7SRui Ueyama template <class ELFT>
841ebc8ed7SRui Ueyama bool LinkerScript::isDiscarded(InputSectionBase<ELFT> *S) {
851ebc8ed7SRui Ueyama   return getOutputSection(S) == "/DISCARD/";
86717677afSRui Ueyama }
87717677afSRui Ueyama 
88481c2ce6SGeorge Rimar template <class ELFT> bool LinkerScript::shouldKeep(InputSectionBase<ELFT> *S) {
89481c2ce6SGeorge Rimar   SectionRule *R = find(S);
90481c2ce6SGeorge Rimar   return R && R->Keep;
91481c2ce6SGeorge Rimar }
92481c2ce6SGeorge Rimar 
93652852c5SGeorge Rimar template <class ELFT>
947c18c28cSRui Ueyama static OutputSectionBase<ELFT> *
957c18c28cSRui Ueyama findSection(std::vector<OutputSectionBase<ELFT> *> &V, StringRef Name) {
967c18c28cSRui Ueyama   for (OutputSectionBase<ELFT> *Sec : V)
977c18c28cSRui Ueyama     if (Sec->getName() == Name)
987c18c28cSRui Ueyama       return Sec;
997c18c28cSRui Ueyama   return nullptr;
1007c18c28cSRui Ueyama }
1017c18c28cSRui Ueyama 
1027c18c28cSRui Ueyama template <class ELFT>
1037c18c28cSRui Ueyama void LinkerScript::assignAddresses(
1047c18c28cSRui Ueyama     std::vector<OutputSectionBase<ELFT> *> &Sections) {
1057c18c28cSRui Ueyama   typedef typename ELFT::uint uintX_t;
1067c18c28cSRui Ueyama 
107652852c5SGeorge Rimar   // Orphan sections are sections present in the input files which
1087c18c28cSRui Ueyama   // are not explicitly placed into the output file by the linker script.
1097c18c28cSRui Ueyama   // We place orphan sections at end of file.
1107c18c28cSRui Ueyama   // Other linkers places them using some heuristics as described in
111652852c5SGeorge Rimar   // https://sourceware.org/binutils/docs/ld/Orphan-Sections.html#Orphan-Sections.
1127c18c28cSRui Ueyama   for (OutputSectionBase<ELFT> *Sec : Sections) {
113652852c5SGeorge Rimar     StringRef Name = Sec->getName();
114652852c5SGeorge Rimar     auto I = std::find(SectionOrder.begin(), SectionOrder.end(), Name);
115652852c5SGeorge Rimar     if (I == SectionOrder.end())
116*9e957a0aSRui Ueyama       Commands.push_back({SectionKind, {}, Name});
117652852c5SGeorge Rimar   }
118652852c5SGeorge Rimar 
1197c18c28cSRui Ueyama   // Assign addresses as instructed by linker script SECTIONS sub-commands.
120652852c5SGeorge Rimar   uintX_t ThreadBssOffset = 0;
121652852c5SGeorge Rimar   uintX_t VA =
122652852c5SGeorge Rimar       Out<ELFT>::ElfHeader->getSize() + Out<ELFT>::ProgramHeaders->getSize();
123652852c5SGeorge Rimar 
124*9e957a0aSRui Ueyama   for (SectionsCommand &Cmd : Commands) {
125*9e957a0aSRui Ueyama     if (Cmd.Kind == ExprKind) {
126*9e957a0aSRui Ueyama       VA = evaluate(Cmd.Expr, VA);
127652852c5SGeorge Rimar       continue;
128652852c5SGeorge Rimar     }
129652852c5SGeorge Rimar 
130*9e957a0aSRui Ueyama     OutputSectionBase<ELFT> *Sec = findSection(Sections, Cmd.SectionName);
1317c18c28cSRui Ueyama     if (!Sec)
132652852c5SGeorge Rimar       continue;
133652852c5SGeorge Rimar 
134652852c5SGeorge Rimar     if ((Sec->getFlags() & SHF_TLS) && Sec->getType() == SHT_NOBITS) {
135652852c5SGeorge Rimar       uintX_t TVA = VA + ThreadBssOffset;
1367c18c28cSRui Ueyama       TVA = alignTo(TVA, Sec->getAlign());
137652852c5SGeorge Rimar       Sec->setVA(TVA);
138652852c5SGeorge Rimar       ThreadBssOffset = TVA - VA + Sec->getSize();
139652852c5SGeorge Rimar       continue;
140652852c5SGeorge Rimar     }
141652852c5SGeorge Rimar 
142652852c5SGeorge Rimar     if (Sec->getFlags() & SHF_ALLOC) {
1437c18c28cSRui Ueyama       VA = alignTo(VA, Sec->getAlign());
144652852c5SGeorge Rimar       Sec->setVA(VA);
145652852c5SGeorge Rimar       VA += Sec->getSize();
146652852c5SGeorge Rimar       continue;
147652852c5SGeorge Rimar     }
148652852c5SGeorge Rimar   }
149652852c5SGeorge Rimar }
150652852c5SGeorge Rimar 
151e2ee72b5SGeorge Rimar ArrayRef<uint8_t> LinkerScript::getFiller(StringRef Name) {
1523e808976SRui Ueyama   auto I = Filler.find(Name);
1533e808976SRui Ueyama   if (I == Filler.end())
154e2ee72b5SGeorge Rimar     return {};
1553e808976SRui Ueyama   return I->second;
156e2ee72b5SGeorge Rimar }
157e2ee72b5SGeorge Rimar 
158e9c58065SRui Ueyama // A compartor to sort output sections. Returns -1 or 1 if both
159e9c58065SRui Ueyama // A and B are mentioned in linker scripts. Otherwise, returns 0
160e9c58065SRui Ueyama // to use the default rule which is implemented in Writer.cpp.
161717677afSRui Ueyama int LinkerScript::compareSections(StringRef A, StringRef B) {
1623e808976SRui Ueyama   auto E = SectionOrder.end();
1633e808976SRui Ueyama   auto I = std::find(SectionOrder.begin(), E, A);
1643e808976SRui Ueyama   auto J = std::find(SectionOrder.begin(), E, B);
1653e808976SRui Ueyama   if (I == E || J == E)
166717677afSRui Ueyama     return 0;
167717677afSRui Ueyama   return I < J ? -1 : 1;
168717677afSRui Ueyama }
169717677afSRui Ueyama 
170cb2aeb66SGeorge Rimar // Returns true if S matches T. S can contain glob meta-characters.
171cb2aeb66SGeorge Rimar // The asterisk ('*') matches zero or more characacters, and the question
172cb2aeb66SGeorge Rimar // mark ('?') matches one character.
1731ebc8ed7SRui Ueyama static bool matchStr(StringRef S, StringRef T) {
1741ebc8ed7SRui Ueyama   for (;;) {
1751ebc8ed7SRui Ueyama     if (S.empty())
1761ebc8ed7SRui Ueyama       return T.empty();
1771ebc8ed7SRui Ueyama     if (S[0] == '*') {
1781ebc8ed7SRui Ueyama       S = S.substr(1);
1791ebc8ed7SRui Ueyama       if (S.empty())
1801ebc8ed7SRui Ueyama         // Fast path. If a pattern is '*', it matches anything.
1811ebc8ed7SRui Ueyama         return true;
1821ebc8ed7SRui Ueyama       for (size_t I = 0, E = T.size(); I < E; ++I)
1831ebc8ed7SRui Ueyama         if (matchStr(S, T.substr(I)))
1841ebc8ed7SRui Ueyama           return true;
1851ebc8ed7SRui Ueyama       return false;
1861ebc8ed7SRui Ueyama     }
187cb2aeb66SGeorge Rimar     if (T.empty() || (S[0] != T[0] && S[0] != '?'))
1881ebc8ed7SRui Ueyama       return false;
1891ebc8ed7SRui Ueyama     S = S.substr(1);
1901ebc8ed7SRui Ueyama     T = T.substr(1);
1911ebc8ed7SRui Ueyama   }
1921ebc8ed7SRui Ueyama }
1931ebc8ed7SRui Ueyama 
1941ebc8ed7SRui Ueyama template <class ELFT> bool SectionRule::match(InputSectionBase<ELFT> *S) {
1951ebc8ed7SRui Ueyama   return matchStr(SectionPattern, S->getSectionName());
1961ebc8ed7SRui Ueyama }
1971ebc8ed7SRui Ueyama 
198e77b5bf6SAdhemerval Zanella class elf::ScriptParser final : public elf::ScriptParserBase {
199c3794e58SGeorge Rimar   typedef void (ScriptParser::*Handler)();
200c3794e58SGeorge Rimar 
201f7c5fbb1SRui Ueyama public:
202717677afSRui Ueyama   ScriptParser(BumpPtrAllocator *A, StringRef S, bool B)
203e77b5bf6SAdhemerval Zanella       : ScriptParserBase(S), Saver(*A), IsUnderSysroot(B) {}
204f23b2320SGeorge Rimar 
205e77b5bf6SAdhemerval Zanella   void run() override;
206f7c5fbb1SRui Ueyama 
207f7c5fbb1SRui Ueyama private:
20852a1509eSRui Ueyama   void addFile(StringRef Path);
20952a1509eSRui Ueyama 
210f7c5fbb1SRui Ueyama   void readAsNeeded();
21190c5099eSDenis Protivensky   void readEntry();
21283f406cfSGeorge Rimar   void readExtern();
213f7c5fbb1SRui Ueyama   void readGroup();
21431aa1f83SRui Ueyama   void readInclude();
215c3794e58SGeorge Rimar   void readNothing() {}
216ee59282bSRui Ueyama   void readOutput();
2179159ce93SDavide Italiano   void readOutputArch();
218f7c5fbb1SRui Ueyama   void readOutputFormat();
21968a39a65SDavide Italiano   void readSearchDir();
2208e3b38abSDenis Protivensky   void readSections();
2218e3b38abSDenis Protivensky 
222652852c5SGeorge Rimar   void readLocationCounterValue();
2238e3b38abSDenis Protivensky   void readOutputSectionDescription();
224481c2ce6SGeorge Rimar   void readSectionPatterns(StringRef OutSec, bool Keep);
225f7c5fbb1SRui Ueyama 
226a47ee68dSRui Ueyama   StringSaver Saver;
227c3794e58SGeorge Rimar   const static StringMap<Handler> Cmd;
22816b0cc9eSSimon Atanasyan   bool IsUnderSysroot;
229f7c5fbb1SRui Ueyama };
230f7c5fbb1SRui Ueyama 
231e0df00b9SRafael Espindola const StringMap<elf::ScriptParser::Handler> elf::ScriptParser::Cmd = {
232c3794e58SGeorge Rimar     {"ENTRY", &ScriptParser::readEntry},
233c3794e58SGeorge Rimar     {"EXTERN", &ScriptParser::readExtern},
234c3794e58SGeorge Rimar     {"GROUP", &ScriptParser::readGroup},
235c3794e58SGeorge Rimar     {"INCLUDE", &ScriptParser::readInclude},
236c3794e58SGeorge Rimar     {"INPUT", &ScriptParser::readGroup},
237c3794e58SGeorge Rimar     {"OUTPUT", &ScriptParser::readOutput},
238c3794e58SGeorge Rimar     {"OUTPUT_ARCH", &ScriptParser::readOutputArch},
239c3794e58SGeorge Rimar     {"OUTPUT_FORMAT", &ScriptParser::readOutputFormat},
240c3794e58SGeorge Rimar     {"SEARCH_DIR", &ScriptParser::readSearchDir},
241c3794e58SGeorge Rimar     {"SECTIONS", &ScriptParser::readSections},
242c3794e58SGeorge Rimar     {";", &ScriptParser::readNothing}};
243c3794e58SGeorge Rimar 
244717677afSRui Ueyama void ScriptParser::run() {
245f7c5fbb1SRui Ueyama   while (!atEOF()) {
246f7c5fbb1SRui Ueyama     StringRef Tok = next();
247c3794e58SGeorge Rimar     if (Handler Fn = Cmd.lookup(Tok))
248c3794e58SGeorge Rimar       (this->*Fn)();
249c3794e58SGeorge Rimar     else
2505761042dSGeorge Rimar       setError("unknown directive: " + Tok);
251f7c5fbb1SRui Ueyama   }
252f7c5fbb1SRui Ueyama }
253f7c5fbb1SRui Ueyama 
254717677afSRui Ueyama void ScriptParser::addFile(StringRef S) {
25516b0cc9eSSimon Atanasyan   if (IsUnderSysroot && S.startswith("/")) {
25616b0cc9eSSimon Atanasyan     SmallString<128> Path;
25716b0cc9eSSimon Atanasyan     (Config->Sysroot + S).toStringRef(Path);
25816b0cc9eSSimon Atanasyan     if (sys::fs::exists(Path)) {
25916b0cc9eSSimon Atanasyan       Driver->addFile(Saver.save(Path.str()));
26016b0cc9eSSimon Atanasyan       return;
26116b0cc9eSSimon Atanasyan     }
26216b0cc9eSSimon Atanasyan   }
26316b0cc9eSSimon Atanasyan 
264f03f3cc1SRui Ueyama   if (sys::path::is_absolute(S)) {
26552a1509eSRui Ueyama     Driver->addFile(S);
26652a1509eSRui Ueyama   } else if (S.startswith("=")) {
26752a1509eSRui Ueyama     if (Config->Sysroot.empty())
26852a1509eSRui Ueyama       Driver->addFile(S.substr(1));
26952a1509eSRui Ueyama     else
27052a1509eSRui Ueyama       Driver->addFile(Saver.save(Config->Sysroot + "/" + S.substr(1)));
27152a1509eSRui Ueyama   } else if (S.startswith("-l")) {
27221eecb4fSRui Ueyama     Driver->addLibrary(S.substr(2));
273a1b8fc3bSSimon Atanasyan   } else if (sys::fs::exists(S)) {
274a1b8fc3bSSimon Atanasyan     Driver->addFile(S);
27552a1509eSRui Ueyama   } else {
27652a1509eSRui Ueyama     std::string Path = findFromSearchPaths(S);
27752a1509eSRui Ueyama     if (Path.empty())
278777f9630SGeorge Rimar       setError("unable to find " + S);
279025d59b1SRui Ueyama     else
28052a1509eSRui Ueyama       Driver->addFile(Saver.save(Path));
28152a1509eSRui Ueyama   }
28252a1509eSRui Ueyama }
28352a1509eSRui Ueyama 
284717677afSRui Ueyama void ScriptParser::readAsNeeded() {
285f7c5fbb1SRui Ueyama   expect("(");
28635da9b6eSRui Ueyama   bool Orig = Config->AsNeeded;
28735da9b6eSRui Ueyama   Config->AsNeeded = true;
288025d59b1SRui Ueyama   while (!Error) {
289f7c5fbb1SRui Ueyama     StringRef Tok = next();
290f7c5fbb1SRui Ueyama     if (Tok == ")")
29135da9b6eSRui Ueyama       break;
29252a1509eSRui Ueyama     addFile(Tok);
293f7c5fbb1SRui Ueyama   }
29435da9b6eSRui Ueyama   Config->AsNeeded = Orig;
295f7c5fbb1SRui Ueyama }
296f7c5fbb1SRui Ueyama 
297717677afSRui Ueyama void ScriptParser::readEntry() {
29890c5099eSDenis Protivensky   // -e <symbol> takes predecence over ENTRY(<symbol>).
29990c5099eSDenis Protivensky   expect("(");
30090c5099eSDenis Protivensky   StringRef Tok = next();
30190c5099eSDenis Protivensky   if (Config->Entry.empty())
30290c5099eSDenis Protivensky     Config->Entry = Tok;
30390c5099eSDenis Protivensky   expect(")");
30490c5099eSDenis Protivensky }
30590c5099eSDenis Protivensky 
306717677afSRui Ueyama void ScriptParser::readExtern() {
30783f406cfSGeorge Rimar   expect("(");
308025d59b1SRui Ueyama   while (!Error) {
30983f406cfSGeorge Rimar     StringRef Tok = next();
31083f406cfSGeorge Rimar     if (Tok == ")")
31183f406cfSGeorge Rimar       return;
31283f406cfSGeorge Rimar     Config->Undefined.push_back(Tok);
31383f406cfSGeorge Rimar   }
31483f406cfSGeorge Rimar }
31583f406cfSGeorge Rimar 
316717677afSRui Ueyama void ScriptParser::readGroup() {
317f7c5fbb1SRui Ueyama   expect("(");
318025d59b1SRui Ueyama   while (!Error) {
319f7c5fbb1SRui Ueyama     StringRef Tok = next();
320f7c5fbb1SRui Ueyama     if (Tok == ")")
321f7c5fbb1SRui Ueyama       return;
322f7c5fbb1SRui Ueyama     if (Tok == "AS_NEEDED") {
323f7c5fbb1SRui Ueyama       readAsNeeded();
324f7c5fbb1SRui Ueyama       continue;
325f7c5fbb1SRui Ueyama     }
32652a1509eSRui Ueyama     addFile(Tok);
327f7c5fbb1SRui Ueyama   }
328f7c5fbb1SRui Ueyama }
329f7c5fbb1SRui Ueyama 
330717677afSRui Ueyama void ScriptParser::readInclude() {
33131aa1f83SRui Ueyama   StringRef Tok = next();
33231aa1f83SRui Ueyama   auto MBOrErr = MemoryBuffer::getFile(Tok);
333025d59b1SRui Ueyama   if (!MBOrErr) {
3345761042dSGeorge Rimar     setError("cannot open " + Tok);
335025d59b1SRui Ueyama     return;
336025d59b1SRui Ueyama   }
33731aa1f83SRui Ueyama   std::unique_ptr<MemoryBuffer> &MB = *MBOrErr;
338a47ee68dSRui Ueyama   StringRef S = Saver.save(MB->getMemBufferRef().getBuffer());
339a47ee68dSRui Ueyama   std::vector<StringRef> V = tokenize(S);
34031aa1f83SRui Ueyama   Tokens.insert(Tokens.begin() + Pos, V.begin(), V.end());
34131aa1f83SRui Ueyama }
34231aa1f83SRui Ueyama 
343717677afSRui Ueyama void ScriptParser::readOutput() {
344ee59282bSRui Ueyama   // -o <file> takes predecence over OUTPUT(<file>).
345ee59282bSRui Ueyama   expect("(");
346ee59282bSRui Ueyama   StringRef Tok = next();
347ee59282bSRui Ueyama   if (Config->OutputFile.empty())
348ee59282bSRui Ueyama     Config->OutputFile = Tok;
349ee59282bSRui Ueyama   expect(")");
350ee59282bSRui Ueyama }
351ee59282bSRui Ueyama 
352717677afSRui Ueyama void ScriptParser::readOutputArch() {
3539159ce93SDavide Italiano   // Error checking only for now.
3549159ce93SDavide Italiano   expect("(");
3559159ce93SDavide Italiano   next();
3569159ce93SDavide Italiano   expect(")");
3579159ce93SDavide Italiano }
3589159ce93SDavide Italiano 
359717677afSRui Ueyama void ScriptParser::readOutputFormat() {
360f7c5fbb1SRui Ueyama   // Error checking only for now.
361f7c5fbb1SRui Ueyama   expect("(");
362f7c5fbb1SRui Ueyama   next();
3636836c618SDavide Italiano   StringRef Tok = next();
3646836c618SDavide Italiano   if (Tok == ")")
3656836c618SDavide Italiano    return;
366025d59b1SRui Ueyama   if (Tok != ",") {
3675761042dSGeorge Rimar     setError("unexpected token: " + Tok);
368025d59b1SRui Ueyama     return;
369025d59b1SRui Ueyama   }
3706836c618SDavide Italiano   next();
3716836c618SDavide Italiano   expect(",");
3726836c618SDavide Italiano   next();
373f7c5fbb1SRui Ueyama   expect(")");
374f7c5fbb1SRui Ueyama }
375f7c5fbb1SRui Ueyama 
376717677afSRui Ueyama void ScriptParser::readSearchDir() {
37768a39a65SDavide Italiano   expect("(");
37806501920SRafael Espindola   Config->SearchPaths.push_back(next());
37968a39a65SDavide Italiano   expect(")");
38068a39a65SDavide Italiano }
38168a39a65SDavide Italiano 
382717677afSRui Ueyama void ScriptParser::readSections() {
383652852c5SGeorge Rimar   Script->DoLayout = true;
3848e3b38abSDenis Protivensky   expect("{");
385652852c5SGeorge Rimar   while (!Error && !skip("}")) {
386652852c5SGeorge Rimar     StringRef Tok = peek();
387652852c5SGeorge Rimar     if (Tok == ".")
388652852c5SGeorge Rimar       readLocationCounterValue();
389652852c5SGeorge Rimar     else
3908e3b38abSDenis Protivensky       readOutputSectionDescription();
3918e3b38abSDenis Protivensky   }
392652852c5SGeorge Rimar }
3938e3b38abSDenis Protivensky 
394481c2ce6SGeorge Rimar void ScriptParser::readSectionPatterns(StringRef OutSec, bool Keep) {
395481c2ce6SGeorge Rimar   expect("(");
396481c2ce6SGeorge Rimar   while (!Error && !skip(")"))
397481c2ce6SGeorge Rimar     Script->Sections.emplace_back(OutSec, next(), Keep);
398481c2ce6SGeorge Rimar }
399481c2ce6SGeorge Rimar 
400652852c5SGeorge Rimar void ScriptParser::readLocationCounterValue() {
401652852c5SGeorge Rimar   expect(".");
402652852c5SGeorge Rimar   expect("=");
403*9e957a0aSRui Ueyama   Script->Commands.push_back({ExprKind, {}, ""});
404*9e957a0aSRui Ueyama   SectionsCommand &Cmd = Script->Commands.back();
405652852c5SGeorge Rimar   while (!Error) {
406652852c5SGeorge Rimar     StringRef Tok = next();
407652852c5SGeorge Rimar     if (Tok == ";")
408652852c5SGeorge Rimar       break;
409*9e957a0aSRui Ueyama     Cmd.Expr.push_back(Tok);
410652852c5SGeorge Rimar   }
411*9e957a0aSRui Ueyama   if (Cmd.Expr.empty())
412652852c5SGeorge Rimar     error("error in location counter expression");
413652852c5SGeorge Rimar }
414652852c5SGeorge Rimar 
415717677afSRui Ueyama void ScriptParser::readOutputSectionDescription() {
4163e808976SRui Ueyama   StringRef OutSec = next();
4173e808976SRui Ueyama   Script->SectionOrder.push_back(OutSec);
418*9e957a0aSRui Ueyama   Script->Commands.push_back({SectionKind, {}, OutSec});
4198e3b38abSDenis Protivensky   expect(":");
4208e3b38abSDenis Protivensky   expect("{");
421025d59b1SRui Ueyama   while (!Error && !skip("}")) {
422481c2ce6SGeorge Rimar     StringRef Tok = next();
423481c2ce6SGeorge Rimar     if (Tok == "*") {
4243e808976SRui Ueyama       readSectionPatterns(OutSec, false);
425481c2ce6SGeorge Rimar     } else if (Tok == "KEEP") {
4268e3b38abSDenis Protivensky       expect("(");
427481c2ce6SGeorge Rimar       next(); // Skip *
4283e808976SRui Ueyama       readSectionPatterns(OutSec, true);
429481c2ce6SGeorge Rimar       expect(")");
430481c2ce6SGeorge Rimar     } else {
431777f9630SGeorge Rimar       setError("unknown command " + Tok);
432481c2ce6SGeorge Rimar     }
4338e3b38abSDenis Protivensky   }
434e2ee72b5SGeorge Rimar   StringRef Tok = peek();
435e2ee72b5SGeorge Rimar   if (Tok.startswith("=")) {
436e2ee72b5SGeorge Rimar     if (!Tok.startswith("=0x")) {
4373ed2f069SRui Ueyama       setError("filler should be a hexadecimal value");
438e2ee72b5SGeorge Rimar       return;
439e2ee72b5SGeorge Rimar     }
4403e808976SRui Ueyama     Tok = Tok.substr(3);
4413e808976SRui Ueyama     Script->Filler[OutSec] = parseHex(Tok);
442e2ee72b5SGeorge Rimar     next();
443e2ee72b5SGeorge Rimar   }
4448e3b38abSDenis Protivensky }
4458e3b38abSDenis Protivensky 
44616b0cc9eSSimon Atanasyan static bool isUnderSysroot(StringRef Path) {
44716b0cc9eSSimon Atanasyan   if (Config->Sysroot == "")
44816b0cc9eSSimon Atanasyan     return false;
44916b0cc9eSSimon Atanasyan   for (; !Path.empty(); Path = sys::path::parent_path(Path))
45016b0cc9eSSimon Atanasyan     if (sys::fs::equivalent(Config->Sysroot, Path))
45116b0cc9eSSimon Atanasyan       return true;
45216b0cc9eSSimon Atanasyan   return false;
45316b0cc9eSSimon Atanasyan }
45416b0cc9eSSimon Atanasyan 
455f7c5fbb1SRui Ueyama // Entry point. The other functions or classes are private to this file.
456f9de0d69SRui Ueyama void LinkerScript::read(MemoryBufferRef MB) {
45716b0cc9eSSimon Atanasyan   StringRef Path = MB.getBufferIdentifier();
458f9de0d69SRui Ueyama   ScriptParser(&Alloc, MB.getBuffer(), isUnderSysroot(Path)).run();
459f7c5fbb1SRui Ueyama }
4601ebc8ed7SRui Ueyama 
4611ebc8ed7SRui Ueyama template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF32LE> *);
4621ebc8ed7SRui Ueyama template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF32BE> *);
4631ebc8ed7SRui Ueyama template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF64LE> *);
4641ebc8ed7SRui Ueyama template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF64BE> *);
4651ebc8ed7SRui Ueyama 
4661ebc8ed7SRui Ueyama template bool LinkerScript::isDiscarded(InputSectionBase<ELF32LE> *);
4671ebc8ed7SRui Ueyama template bool LinkerScript::isDiscarded(InputSectionBase<ELF32BE> *);
4681ebc8ed7SRui Ueyama template bool LinkerScript::isDiscarded(InputSectionBase<ELF64LE> *);
4691ebc8ed7SRui Ueyama template bool LinkerScript::isDiscarded(InputSectionBase<ELF64BE> *);
4701ebc8ed7SRui Ueyama 
471481c2ce6SGeorge Rimar template bool LinkerScript::shouldKeep(InputSectionBase<ELF32LE> *);
472481c2ce6SGeorge Rimar template bool LinkerScript::shouldKeep(InputSectionBase<ELF32BE> *);
473481c2ce6SGeorge Rimar template bool LinkerScript::shouldKeep(InputSectionBase<ELF64LE> *);
474481c2ce6SGeorge Rimar template bool LinkerScript::shouldKeep(InputSectionBase<ELF64BE> *);
475652852c5SGeorge Rimar 
476652852c5SGeorge Rimar template void
477652852c5SGeorge Rimar LinkerScript::assignAddresses(std::vector<OutputSectionBase<ELF32LE> *> &);
478652852c5SGeorge Rimar template void
479652852c5SGeorge Rimar LinkerScript::assignAddresses(std::vector<OutputSectionBase<ELF32BE> *> &);
480652852c5SGeorge Rimar template void
481652852c5SGeorge Rimar LinkerScript::assignAddresses(std::vector<OutputSectionBase<ELF64LE> *> &);
482652852c5SGeorge Rimar template void
483652852c5SGeorge Rimar LinkerScript::assignAddresses(std::vector<OutputSectionBase<ELF64BE> *> &);
484