blob: af9704a4d396a3c3a5118a66a850a3d9ad65e0ec [file] [log] [blame]
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +00001//===- LinkerScript.cpp ---------------------------------------------------===//
2//
3// The LLVM Linker
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file contains the parser/evaluator of the linker script.
11// It does not construct an AST but consume linker script directives directly.
Rui Ueyama34f29242015-10-13 19:51:57 +000012// Results are written to Driver or Config object.
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +000013//
14//===----------------------------------------------------------------------===//
15
Rui Ueyama717677a2016-02-11 21:17:59 +000016#include "LinkerScript.h"
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +000017#include "Config.h"
18#include "Driver.h"
Rui Ueyama1ebc8ed2016-02-12 21:47:28 +000019#include "InputSection.h"
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +000020#include "SymbolTable.h"
21#include "llvm/Support/FileSystem.h"
22#include "llvm/Support/MemoryBuffer.h"
Rui Ueyamaf03f3cc2015-10-13 00:09:21 +000023#include "llvm/Support/Path.h"
Rui Ueyamaa47ee682015-10-11 01:53:04 +000024#include "llvm/Support/StringSaver.h"
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +000025
26using namespace llvm;
Rui Ueyama1ebc8ed2016-02-12 21:47:28 +000027using namespace llvm::object;
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +000028using namespace lld;
29using namespace lld::elf2;
30
Rui Ueyama717677a2016-02-11 21:17:59 +000031LinkerScript *elf2::Script;
32
Rui Ueyama1ebc8ed2016-02-12 21:47:28 +000033template <class ELFT>
George Rimar481c2ce2016-02-23 07:47:54 +000034SectionRule *LinkerScript::find(InputSectionBase<ELFT> *S) {
Rui Ueyama1ebc8ed2016-02-12 21:47:28 +000035 for (SectionRule &R : Sections)
36 if (R.match(S))
George Rimar481c2ce2016-02-23 07:47:54 +000037 return &R;
38 return nullptr;
39}
40
41template <class ELFT>
42StringRef LinkerScript::getOutputSection(InputSectionBase<ELFT> *S) {
43 SectionRule *R = find(S);
44 return R ? R->Dest : "";
Rui Ueyama717677a2016-02-11 21:17:59 +000045}
46
Rui Ueyama1ebc8ed2016-02-12 21:47:28 +000047template <class ELFT>
48bool LinkerScript::isDiscarded(InputSectionBase<ELFT> *S) {
49 return getOutputSection(S) == "/DISCARD/";
Rui Ueyama717677a2016-02-11 21:17:59 +000050}
51
George Rimar481c2ce2016-02-23 07:47:54 +000052template <class ELFT> bool LinkerScript::shouldKeep(InputSectionBase<ELFT> *S) {
53 SectionRule *R = find(S);
54 return R && R->Keep;
55}
56
Rui Ueyamae9c58062016-02-12 20:41:43 +000057// A compartor to sort output sections. Returns -1 or 1 if both
58// A and B are mentioned in linker scripts. Otherwise, returns 0
59// to use the default rule which is implemented in Writer.cpp.
Rui Ueyama717677a2016-02-11 21:17:59 +000060int LinkerScript::compareSections(StringRef A, StringRef B) {
Rui Ueyamae9c58062016-02-12 20:41:43 +000061 auto E = SectionOrder.end();
62 auto I = std::find(SectionOrder.begin(), E, A);
63 auto J = std::find(SectionOrder.begin(), E, B);
64 if (I == E || J == E)
Rui Ueyama717677a2016-02-11 21:17:59 +000065 return 0;
66 return I < J ? -1 : 1;
67}
68
George Rimarcb2aeb62016-02-24 08:49:50 +000069// Returns true if S matches T. S can contain glob meta-characters.
70// The asterisk ('*') matches zero or more characacters, and the question
71// mark ('?') matches one character.
Rui Ueyama1ebc8ed2016-02-12 21:47:28 +000072static bool matchStr(StringRef S, StringRef T) {
73 for (;;) {
74 if (S.empty())
75 return T.empty();
76 if (S[0] == '*') {
77 S = S.substr(1);
78 if (S.empty())
79 // Fast path. If a pattern is '*', it matches anything.
80 return true;
81 for (size_t I = 0, E = T.size(); I < E; ++I)
82 if (matchStr(S, T.substr(I)))
83 return true;
84 return false;
85 }
George Rimarcb2aeb62016-02-24 08:49:50 +000086 if (T.empty() || (S[0] != T[0] && S[0] != '?'))
Rui Ueyama1ebc8ed2016-02-12 21:47:28 +000087 return false;
88 S = S.substr(1);
89 T = T.substr(1);
90 }
91}
92
93template <class ELFT> bool SectionRule::match(InputSectionBase<ELFT> *S) {
94 return matchStr(SectionPattern, S->getSectionName());
95}
96
Rui Ueyama717677a2016-02-11 21:17:59 +000097class elf2::ScriptParser {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +000098public:
Rui Ueyama717677a2016-02-11 21:17:59 +000099 ScriptParser(BumpPtrAllocator *A, StringRef S, bool B)
George Rimarf23b2322016-02-19 10:45:45 +0000100 : Saver(*A), Tokens(tokenize(S)), IsUnderSysroot(B) {
George Rimard2389bf2016-02-19 11:56:49 +0000101 Cmd["ENTRY"] = std::mem_fn(&ScriptParser::readEntry);
102 Cmd["EXTERN"] = std::mem_fn(&ScriptParser::readExtern);
103 Cmd["GROUP"] = std::mem_fn(&ScriptParser::readGroup);
104 Cmd["INCLUDE"] = std::mem_fn(&ScriptParser::readInclude);
105 Cmd["INPUT"] = std::mem_fn(&ScriptParser::readGroup);
106 Cmd["OUTPUT"] = std::mem_fn(&ScriptParser::readOutput);
107 Cmd["OUTPUT_ARCH"] = std::mem_fn(&ScriptParser::readOutputArch);
108 Cmd["OUTPUT_FORMAT"] = std::mem_fn(&ScriptParser::readOutputFormat);
109 Cmd["SEARCH_DIR"] = std::mem_fn(&ScriptParser::readSearchDir);
110 Cmd["SECTIONS"] = std::mem_fn(&ScriptParser::readSections);
George Rimarf23b2322016-02-19 10:45:45 +0000111 Cmd[";"] = [](ScriptParser &) {};
112 }
113
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000114 void run();
115
116private:
Rui Ueyama025d59b2016-02-02 20:27:59 +0000117 void setError(const Twine &Msg);
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000118 static std::vector<StringRef> tokenize(StringRef S);
119 static StringRef skipSpace(StringRef S);
Rui Ueyama025d59b2016-02-02 20:27:59 +0000120 bool atEOF();
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000121 StringRef next();
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000122 bool skip(StringRef Tok);
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000123 void expect(StringRef Expect);
124
Rui Ueyama52a15092015-10-11 03:28:42 +0000125 void addFile(StringRef Path);
126
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000127 void readAsNeeded();
Denis Protivensky90c50992015-10-08 06:48:38 +0000128 void readEntry();
George Rimar83f406c2015-10-19 17:35:12 +0000129 void readExtern();
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000130 void readGroup();
Rui Ueyama31aa1f82015-10-11 01:31:55 +0000131 void readInclude();
Rui Ueyamaee592822015-10-07 00:25:09 +0000132 void readOutput();
Davide Italiano9159ce92015-10-12 21:50:08 +0000133 void readOutputArch();
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000134 void readOutputFormat();
Davide Italiano68a39a62015-10-08 17:51:41 +0000135 void readSearchDir();
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000136 void readSections();
137
138 void readOutputSectionDescription();
George Rimar481c2ce2016-02-23 07:47:54 +0000139 void readSectionPatterns(StringRef OutSec, bool Keep);
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000140
Rui Ueyamaa47ee682015-10-11 01:53:04 +0000141 StringSaver Saver;
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000142 std::vector<StringRef> Tokens;
George Rimarf23b2322016-02-19 10:45:45 +0000143 llvm::StringMap<std::function<void(ScriptParser &)>> Cmd;
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000144 size_t Pos = 0;
Simon Atanasyan16b0cc92015-11-26 05:53:00 +0000145 bool IsUnderSysroot;
George Rimarf23b2322016-02-19 10:45:45 +0000146 bool Error = false;
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000147};
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000148
Rui Ueyama717677a2016-02-11 21:17:59 +0000149void ScriptParser::run() {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000150 while (!atEOF()) {
151 StringRef Tok = next();
George Rimarf23b2322016-02-19 10:45:45 +0000152 auto It = Cmd.find(Tok);
153 if (It != Cmd.end()) {
154 std::function<void(ScriptParser &)> &Handler = It->second;
155 Handler(*this);
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000156 } else {
Rui Ueyama025d59b2016-02-02 20:27:59 +0000157 setError("unknown directive: " + Tok);
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000158 }
159 }
160}
161
Rui Ueyama025d59b2016-02-02 20:27:59 +0000162// We don't want to record cascading errors. Keep only the first one.
Rui Ueyama717677a2016-02-11 21:17:59 +0000163void ScriptParser::setError(const Twine &Msg) {
Rui Ueyama025d59b2016-02-02 20:27:59 +0000164 if (Error)
165 return;
166 error(Msg);
167 Error = true;
168}
169
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000170// Split S into linker script tokens.
Rui Ueyama717677a2016-02-11 21:17:59 +0000171std::vector<StringRef> ScriptParser::tokenize(StringRef S) {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000172 std::vector<StringRef> Ret;
173 for (;;) {
174 S = skipSpace(S);
175 if (S.empty())
176 return Ret;
177
178 // Quoted token
179 if (S.startswith("\"")) {
180 size_t E = S.find("\"", 1);
Rui Ueyama025d59b2016-02-02 20:27:59 +0000181 if (E == StringRef::npos) {
182 error("unclosed quote");
183 return {};
184 }
Pete Cooper60259332016-01-22 23:46:37 +0000185 Ret.push_back(S.substr(1, E - 1));
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000186 S = S.substr(E + 1);
187 continue;
188 }
189
190 // Unquoted token
191 size_t Pos = S.find_first_not_of(
192 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
193 "0123456789_.$/\\~=+[]*?-:");
194 // A character that cannot start a word (which is usually a
195 // punctuation) forms a single character token.
196 if (Pos == 0)
197 Pos = 1;
198 Ret.push_back(S.substr(0, Pos));
199 S = S.substr(Pos);
200 }
201}
202
203// Skip leading whitespace characters or /**/-style comments.
Rui Ueyama717677a2016-02-11 21:17:59 +0000204StringRef ScriptParser::skipSpace(StringRef S) {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000205 for (;;) {
206 if (S.startswith("/*")) {
207 size_t E = S.find("*/", 2);
Rui Ueyama025d59b2016-02-02 20:27:59 +0000208 if (E == StringRef::npos) {
209 error("unclosed comment in a linker script");
210 return "";
211 }
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000212 S = S.substr(E + 2);
213 continue;
214 }
215 size_t Size = S.size();
216 S = S.ltrim();
217 if (S.size() == Size)
218 return S;
219 }
220}
221
Rui Ueyama025d59b2016-02-02 20:27:59 +0000222// An errneous token is handled as if it were the last token before EOF.
Rui Ueyama717677a2016-02-11 21:17:59 +0000223bool ScriptParser::atEOF() { return Error || Tokens.size() == Pos; }
Rui Ueyama025d59b2016-02-02 20:27:59 +0000224
Rui Ueyama717677a2016-02-11 21:17:59 +0000225StringRef ScriptParser::next() {
Rui Ueyama025d59b2016-02-02 20:27:59 +0000226 if (Error)
227 return "";
228 if (atEOF()) {
229 setError("unexpected EOF");
230 return "";
231 }
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000232 return Tokens[Pos++];
233}
234
Rui Ueyama717677a2016-02-11 21:17:59 +0000235bool ScriptParser::skip(StringRef Tok) {
Rui Ueyama025d59b2016-02-02 20:27:59 +0000236 if (Error)
237 return false;
238 if (atEOF()) {
239 setError("unexpected EOF");
240 return false;
241 }
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000242 if (Tok != Tokens[Pos])
243 return false;
244 ++Pos;
245 return true;
246}
247
Rui Ueyama717677a2016-02-11 21:17:59 +0000248void ScriptParser::expect(StringRef Expect) {
Rui Ueyama025d59b2016-02-02 20:27:59 +0000249 if (Error)
250 return;
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000251 StringRef Tok = next();
252 if (Tok != Expect)
Rui Ueyama025d59b2016-02-02 20:27:59 +0000253 setError(Expect + " expected, but got " + Tok);
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000254}
255
Rui Ueyama717677a2016-02-11 21:17:59 +0000256void ScriptParser::addFile(StringRef S) {
Simon Atanasyan16b0cc92015-11-26 05:53:00 +0000257 if (IsUnderSysroot && S.startswith("/")) {
258 SmallString<128> Path;
259 (Config->Sysroot + S).toStringRef(Path);
260 if (sys::fs::exists(Path)) {
261 Driver->addFile(Saver.save(Path.str()));
262 return;
263 }
264 }
265
Rui Ueyamaf03f3cc2015-10-13 00:09:21 +0000266 if (sys::path::is_absolute(S)) {
Rui Ueyama52a15092015-10-11 03:28:42 +0000267 Driver->addFile(S);
268 } else if (S.startswith("=")) {
269 if (Config->Sysroot.empty())
270 Driver->addFile(S.substr(1));
271 else
272 Driver->addFile(Saver.save(Config->Sysroot + "/" + S.substr(1)));
273 } else if (S.startswith("-l")) {
Rui Ueyama21eecb42016-02-02 21:13:09 +0000274 Driver->addLibrary(S.substr(2));
Simon Atanasyana1b8fc32015-11-26 20:23:46 +0000275 } else if (sys::fs::exists(S)) {
276 Driver->addFile(S);
Rui Ueyama52a15092015-10-11 03:28:42 +0000277 } else {
278 std::string Path = findFromSearchPaths(S);
279 if (Path.empty())
Rui Ueyama025d59b2016-02-02 20:27:59 +0000280 setError("Unable to find " + S);
281 else
282 Driver->addFile(Saver.save(Path));
Rui Ueyama52a15092015-10-11 03:28:42 +0000283 }
284}
285
Rui Ueyama717677a2016-02-11 21:17:59 +0000286void ScriptParser::readAsNeeded() {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000287 expect("(");
Rui Ueyama35da9b62015-10-11 20:59:12 +0000288 bool Orig = Config->AsNeeded;
289 Config->AsNeeded = true;
Rui Ueyama025d59b2016-02-02 20:27:59 +0000290 while (!Error) {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000291 StringRef Tok = next();
292 if (Tok == ")")
Rui Ueyama35da9b62015-10-11 20:59:12 +0000293 break;
Rui Ueyama52a15092015-10-11 03:28:42 +0000294 addFile(Tok);
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000295 }
Rui Ueyama35da9b62015-10-11 20:59:12 +0000296 Config->AsNeeded = Orig;
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000297}
298
Rui Ueyama717677a2016-02-11 21:17:59 +0000299void ScriptParser::readEntry() {
Denis Protivensky90c50992015-10-08 06:48:38 +0000300 // -e <symbol> takes predecence over ENTRY(<symbol>).
301 expect("(");
302 StringRef Tok = next();
303 if (Config->Entry.empty())
304 Config->Entry = Tok;
305 expect(")");
306}
307
Rui Ueyama717677a2016-02-11 21:17:59 +0000308void ScriptParser::readExtern() {
George Rimar83f406c2015-10-19 17:35:12 +0000309 expect("(");
Rui Ueyama025d59b2016-02-02 20:27:59 +0000310 while (!Error) {
George Rimar83f406c2015-10-19 17:35:12 +0000311 StringRef Tok = next();
312 if (Tok == ")")
313 return;
314 Config->Undefined.push_back(Tok);
315 }
316}
317
Rui Ueyama717677a2016-02-11 21:17:59 +0000318void ScriptParser::readGroup() {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000319 expect("(");
Rui Ueyama025d59b2016-02-02 20:27:59 +0000320 while (!Error) {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000321 StringRef Tok = next();
322 if (Tok == ")")
323 return;
324 if (Tok == "AS_NEEDED") {
325 readAsNeeded();
326 continue;
327 }
Rui Ueyama52a15092015-10-11 03:28:42 +0000328 addFile(Tok);
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000329 }
330}
331
Rui Ueyama717677a2016-02-11 21:17:59 +0000332void ScriptParser::readInclude() {
Rui Ueyama31aa1f82015-10-11 01:31:55 +0000333 StringRef Tok = next();
334 auto MBOrErr = MemoryBuffer::getFile(Tok);
Rui Ueyama025d59b2016-02-02 20:27:59 +0000335 if (!MBOrErr) {
336 setError("cannot open " + Tok);
337 return;
338 }
Rui Ueyama31aa1f82015-10-11 01:31:55 +0000339 std::unique_ptr<MemoryBuffer> &MB = *MBOrErr;
Rui Ueyamaa47ee682015-10-11 01:53:04 +0000340 StringRef S = Saver.save(MB->getMemBufferRef().getBuffer());
341 std::vector<StringRef> V = tokenize(S);
Rui Ueyama31aa1f82015-10-11 01:31:55 +0000342 Tokens.insert(Tokens.begin() + Pos, V.begin(), V.end());
Rui Ueyama31aa1f82015-10-11 01:31:55 +0000343}
344
Rui Ueyama717677a2016-02-11 21:17:59 +0000345void ScriptParser::readOutput() {
Rui Ueyamaee592822015-10-07 00:25:09 +0000346 // -o <file> takes predecence over OUTPUT(<file>).
347 expect("(");
348 StringRef Tok = next();
349 if (Config->OutputFile.empty())
350 Config->OutputFile = Tok;
351 expect(")");
352}
353
Rui Ueyama717677a2016-02-11 21:17:59 +0000354void ScriptParser::readOutputArch() {
Davide Italiano9159ce92015-10-12 21:50:08 +0000355 // Error checking only for now.
356 expect("(");
357 next();
358 expect(")");
359}
360
Rui Ueyama717677a2016-02-11 21:17:59 +0000361void ScriptParser::readOutputFormat() {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000362 // Error checking only for now.
363 expect("(");
364 next();
Davide Italiano6836c612015-10-12 21:08:41 +0000365 StringRef Tok = next();
366 if (Tok == ")")
367 return;
Rui Ueyama025d59b2016-02-02 20:27:59 +0000368 if (Tok != ",") {
369 setError("unexpected token: " + Tok);
370 return;
371 }
Davide Italiano6836c612015-10-12 21:08:41 +0000372 next();
373 expect(",");
374 next();
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000375 expect(")");
376}
377
Rui Ueyama717677a2016-02-11 21:17:59 +0000378void ScriptParser::readSearchDir() {
Davide Italiano68a39a62015-10-08 17:51:41 +0000379 expect("(");
Rui Ueyama52a15092015-10-11 03:28:42 +0000380 Config->SearchPaths.push_back(next());
Davide Italiano68a39a62015-10-08 17:51:41 +0000381 expect(")");
382}
383
Rui Ueyama717677a2016-02-11 21:17:59 +0000384void ScriptParser::readSections() {
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000385 expect("{");
Rui Ueyama025d59b2016-02-02 20:27:59 +0000386 while (!Error && !skip("}"))
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000387 readOutputSectionDescription();
388}
389
George Rimar481c2ce2016-02-23 07:47:54 +0000390void ScriptParser::readSectionPatterns(StringRef OutSec, bool Keep) {
391 expect("(");
392 while (!Error && !skip(")"))
393 Script->Sections.emplace_back(OutSec, next(), Keep);
394}
395
Rui Ueyama717677a2016-02-11 21:17:59 +0000396void ScriptParser::readOutputSectionDescription() {
Rui Ueyamae9c58062016-02-12 20:41:43 +0000397 StringRef OutSec = next();
398 Script->SectionOrder.push_back(OutSec);
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000399 expect(":");
400 expect("{");
Rui Ueyama025d59b2016-02-02 20:27:59 +0000401 while (!Error && !skip("}")) {
George Rimar481c2ce2016-02-23 07:47:54 +0000402 StringRef Tok = next();
403 if (Tok == "*") {
404 readSectionPatterns(OutSec, false);
405 } else if (Tok == "KEEP") {
406 expect("(");
407 next(); // Skip *
408 readSectionPatterns(OutSec, true);
409 expect(")");
410 } else {
411 setError("Unknown command " + Tok);
412 }
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000413 }
414}
415
Simon Atanasyan16b0cc92015-11-26 05:53:00 +0000416static bool isUnderSysroot(StringRef Path) {
417 if (Config->Sysroot == "")
418 return false;
419 for (; !Path.empty(); Path = sys::path::parent_path(Path))
420 if (sys::fs::equivalent(Config->Sysroot, Path))
421 return true;
422 return false;
423}
424
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000425// Entry point. The other functions or classes are private to this file.
Rui Ueyamaf9de0d62016-02-11 21:38:55 +0000426void LinkerScript::read(MemoryBufferRef MB) {
Simon Atanasyan16b0cc92015-11-26 05:53:00 +0000427 StringRef Path = MB.getBufferIdentifier();
Rui Ueyamaf9de0d62016-02-11 21:38:55 +0000428 ScriptParser(&Alloc, MB.getBuffer(), isUnderSysroot(Path)).run();
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000429}
Rui Ueyama1ebc8ed2016-02-12 21:47:28 +0000430
431template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF32LE> *);
432template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF32BE> *);
433template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF64LE> *);
434template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF64BE> *);
435
436template bool LinkerScript::isDiscarded(InputSectionBase<ELF32LE> *);
437template bool LinkerScript::isDiscarded(InputSectionBase<ELF32BE> *);
438template bool LinkerScript::isDiscarded(InputSectionBase<ELF64LE> *);
439template bool LinkerScript::isDiscarded(InputSectionBase<ELF64BE> *);
440
George Rimar481c2ce2016-02-23 07:47:54 +0000441template bool LinkerScript::shouldKeep(InputSectionBase<ELF32LE> *);
442template bool LinkerScript::shouldKeep(InputSectionBase<ELF32BE> *);
443template bool LinkerScript::shouldKeep(InputSectionBase<ELF64LE> *);
444template bool LinkerScript::shouldKeep(InputSectionBase<ELF64BE> *);
445
Rui Ueyama1ebc8ed2016-02-12 21:47:28 +0000446template bool SectionRule::match(InputSectionBase<ELF32LE> *);
447template bool SectionRule::match(InputSectionBase<ELF32BE> *);
448template bool SectionRule::match(InputSectionBase<ELF64LE> *);
449template bool SectionRule::match(InputSectionBase<ELF64BE> *);