blob: a146be0ebc7279ceb71a701e3ef3a3eb2496e9b1 [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
George Rimare2ee72b2016-02-26 14:48:31 +000057ArrayRef<uint8_t> LinkerScript::getFiller(StringRef Name) {
58 for (OutSection &C : OutSections)
59 if (C.Name == Name)
60 return C.Filler;
61 return {};
62}
63
Rui Ueyamae9c58062016-02-12 20:41:43 +000064// A compartor to sort output sections. Returns -1 or 1 if both
65// A and B are mentioned in linker scripts. Otherwise, returns 0
66// to use the default rule which is implemented in Writer.cpp.
Rui Ueyama717677a2016-02-11 21:17:59 +000067int LinkerScript::compareSections(StringRef A, StringRef B) {
George Rimare2ee72b2016-02-26 14:48:31 +000068 auto E = OutSections.end();
69 auto I = std::find_if(OutSections.begin(), E,
70 [&](OutSection &C) { return C.Name == A; });
71 auto J = std::find_if(OutSections.begin(), E,
72 [&](OutSection &C) { return C.Name == B; });
Rui Ueyamae9c58062016-02-12 20:41:43 +000073 if (I == E || J == E)
Rui Ueyama717677a2016-02-11 21:17:59 +000074 return 0;
75 return I < J ? -1 : 1;
76}
77
George Rimarcb2aeb62016-02-24 08:49:50 +000078// Returns true if S matches T. S can contain glob meta-characters.
79// The asterisk ('*') matches zero or more characacters, and the question
80// mark ('?') matches one character.
Rui Ueyama1ebc8ed2016-02-12 21:47:28 +000081static bool matchStr(StringRef S, StringRef T) {
82 for (;;) {
83 if (S.empty())
84 return T.empty();
85 if (S[0] == '*') {
86 S = S.substr(1);
87 if (S.empty())
88 // Fast path. If a pattern is '*', it matches anything.
89 return true;
90 for (size_t I = 0, E = T.size(); I < E; ++I)
91 if (matchStr(S, T.substr(I)))
92 return true;
93 return false;
94 }
George Rimarcb2aeb62016-02-24 08:49:50 +000095 if (T.empty() || (S[0] != T[0] && S[0] != '?'))
Rui Ueyama1ebc8ed2016-02-12 21:47:28 +000096 return false;
97 S = S.substr(1);
98 T = T.substr(1);
99 }
100}
101
102template <class ELFT> bool SectionRule::match(InputSectionBase<ELFT> *S) {
103 return matchStr(SectionPattern, S->getSectionName());
104}
105
Rui Ueyama717677a2016-02-11 21:17:59 +0000106class elf2::ScriptParser {
George Rimarc3794e52016-02-24 09:21:47 +0000107 typedef void (ScriptParser::*Handler)();
108
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000109public:
Rui Ueyama717677a2016-02-11 21:17:59 +0000110 ScriptParser(BumpPtrAllocator *A, StringRef S, bool B)
George Rimarc3794e52016-02-24 09:21:47 +0000111 : Saver(*A), Tokens(tokenize(S)), IsUnderSysroot(B) {}
George Rimarf23b2322016-02-19 10:45:45 +0000112
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000113 void run();
114
115private:
Rui Ueyama025d59b2016-02-02 20:27:59 +0000116 void setError(const Twine &Msg);
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000117 static std::vector<StringRef> tokenize(StringRef S);
118 static StringRef skipSpace(StringRef S);
Rui Ueyama025d59b2016-02-02 20:27:59 +0000119 bool atEOF();
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000120 StringRef next();
George Rimare2ee72b2016-02-26 14:48:31 +0000121 StringRef peek();
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();
George Rimarc3794e52016-02-24 09:21:47 +0000132 void readNothing() {}
Rui Ueyamaee592822015-10-07 00:25:09 +0000133 void readOutput();
Davide Italiano9159ce92015-10-12 21:50:08 +0000134 void readOutputArch();
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000135 void readOutputFormat();
Davide Italiano68a39a62015-10-08 17:51:41 +0000136 void readSearchDir();
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000137 void readSections();
138
139 void readOutputSectionDescription();
George Rimar481c2ce2016-02-23 07:47:54 +0000140 void readSectionPatterns(StringRef OutSec, bool Keep);
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000141
George Rimare2ee72b2016-02-26 14:48:31 +0000142 std::vector<uint8_t> parseHex(StringRef S);
143
Rui Ueyamaa47ee682015-10-11 01:53:04 +0000144 StringSaver Saver;
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000145 std::vector<StringRef> Tokens;
George Rimarc3794e52016-02-24 09:21:47 +0000146 const static StringMap<Handler> Cmd;
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000147 size_t Pos = 0;
Simon Atanasyan16b0cc92015-11-26 05:53:00 +0000148 bool IsUnderSysroot;
George Rimarf23b2322016-02-19 10:45:45 +0000149 bool Error = false;
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000150};
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000151
George Rimarc3794e52016-02-24 09:21:47 +0000152const StringMap<elf2::ScriptParser::Handler> elf2::ScriptParser::Cmd = {
153 {"ENTRY", &ScriptParser::readEntry},
154 {"EXTERN", &ScriptParser::readExtern},
155 {"GROUP", &ScriptParser::readGroup},
156 {"INCLUDE", &ScriptParser::readInclude},
157 {"INPUT", &ScriptParser::readGroup},
158 {"OUTPUT", &ScriptParser::readOutput},
159 {"OUTPUT_ARCH", &ScriptParser::readOutputArch},
160 {"OUTPUT_FORMAT", &ScriptParser::readOutputFormat},
161 {"SEARCH_DIR", &ScriptParser::readSearchDir},
162 {"SECTIONS", &ScriptParser::readSections},
163 {";", &ScriptParser::readNothing}};
164
Rui Ueyama717677a2016-02-11 21:17:59 +0000165void ScriptParser::run() {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000166 while (!atEOF()) {
167 StringRef Tok = next();
George Rimarc3794e52016-02-24 09:21:47 +0000168 if (Handler Fn = Cmd.lookup(Tok))
169 (this->*Fn)();
170 else
Rui Ueyama025d59b2016-02-02 20:27:59 +0000171 setError("unknown directive: " + Tok);
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000172 }
173}
174
Rui Ueyama025d59b2016-02-02 20:27:59 +0000175// We don't want to record cascading errors. Keep only the first one.
Rui Ueyama717677a2016-02-11 21:17:59 +0000176void ScriptParser::setError(const Twine &Msg) {
Rui Ueyama025d59b2016-02-02 20:27:59 +0000177 if (Error)
178 return;
179 error(Msg);
180 Error = true;
181}
182
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000183// Split S into linker script tokens.
Rui Ueyama717677a2016-02-11 21:17:59 +0000184std::vector<StringRef> ScriptParser::tokenize(StringRef S) {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000185 std::vector<StringRef> Ret;
186 for (;;) {
187 S = skipSpace(S);
188 if (S.empty())
189 return Ret;
190
191 // Quoted token
192 if (S.startswith("\"")) {
193 size_t E = S.find("\"", 1);
Rui Ueyama025d59b2016-02-02 20:27:59 +0000194 if (E == StringRef::npos) {
195 error("unclosed quote");
196 return {};
197 }
Pete Cooper60259332016-01-22 23:46:37 +0000198 Ret.push_back(S.substr(1, E - 1));
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000199 S = S.substr(E + 1);
200 continue;
201 }
202
203 // Unquoted token
204 size_t Pos = S.find_first_not_of(
205 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
206 "0123456789_.$/\\~=+[]*?-:");
207 // A character that cannot start a word (which is usually a
208 // punctuation) forms a single character token.
209 if (Pos == 0)
210 Pos = 1;
211 Ret.push_back(S.substr(0, Pos));
212 S = S.substr(Pos);
213 }
214}
215
216// Skip leading whitespace characters or /**/-style comments.
Rui Ueyama717677a2016-02-11 21:17:59 +0000217StringRef ScriptParser::skipSpace(StringRef S) {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000218 for (;;) {
219 if (S.startswith("/*")) {
220 size_t E = S.find("*/", 2);
Rui Ueyama025d59b2016-02-02 20:27:59 +0000221 if (E == StringRef::npos) {
222 error("unclosed comment in a linker script");
223 return "";
224 }
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000225 S = S.substr(E + 2);
226 continue;
227 }
228 size_t Size = S.size();
229 S = S.ltrim();
230 if (S.size() == Size)
231 return S;
232 }
233}
234
Rui Ueyama025d59b2016-02-02 20:27:59 +0000235// An errneous token is handled as if it were the last token before EOF.
Rui Ueyama717677a2016-02-11 21:17:59 +0000236bool ScriptParser::atEOF() { return Error || Tokens.size() == Pos; }
Rui Ueyama025d59b2016-02-02 20:27:59 +0000237
Rui Ueyama717677a2016-02-11 21:17:59 +0000238StringRef ScriptParser::next() {
Rui Ueyama025d59b2016-02-02 20:27:59 +0000239 if (Error)
240 return "";
241 if (atEOF()) {
242 setError("unexpected EOF");
243 return "";
244 }
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000245 return Tokens[Pos++];
246}
247
George Rimare2ee72b2016-02-26 14:48:31 +0000248StringRef ScriptParser::peek() {
249 StringRef Tok = next();
250 if (Error)
251 return "";
252 --Pos;
253 return Tok;
254}
255
Rui Ueyama717677a2016-02-11 21:17:59 +0000256bool ScriptParser::skip(StringRef Tok) {
Rui Ueyama025d59b2016-02-02 20:27:59 +0000257 if (Error)
258 return false;
259 if (atEOF()) {
260 setError("unexpected EOF");
261 return false;
262 }
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000263 if (Tok != Tokens[Pos])
264 return false;
265 ++Pos;
266 return true;
267}
268
Rui Ueyama717677a2016-02-11 21:17:59 +0000269void ScriptParser::expect(StringRef Expect) {
Rui Ueyama025d59b2016-02-02 20:27:59 +0000270 if (Error)
271 return;
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000272 StringRef Tok = next();
273 if (Tok != Expect)
Rui Ueyama025d59b2016-02-02 20:27:59 +0000274 setError(Expect + " expected, but got " + Tok);
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000275}
276
Rui Ueyama717677a2016-02-11 21:17:59 +0000277void ScriptParser::addFile(StringRef S) {
Simon Atanasyan16b0cc92015-11-26 05:53:00 +0000278 if (IsUnderSysroot && S.startswith("/")) {
279 SmallString<128> Path;
280 (Config->Sysroot + S).toStringRef(Path);
281 if (sys::fs::exists(Path)) {
282 Driver->addFile(Saver.save(Path.str()));
283 return;
284 }
285 }
286
Rui Ueyamaf03f3cc2015-10-13 00:09:21 +0000287 if (sys::path::is_absolute(S)) {
Rui Ueyama52a15092015-10-11 03:28:42 +0000288 Driver->addFile(S);
289 } else if (S.startswith("=")) {
290 if (Config->Sysroot.empty())
291 Driver->addFile(S.substr(1));
292 else
293 Driver->addFile(Saver.save(Config->Sysroot + "/" + S.substr(1)));
294 } else if (S.startswith("-l")) {
Rui Ueyama21eecb42016-02-02 21:13:09 +0000295 Driver->addLibrary(S.substr(2));
Simon Atanasyana1b8fc32015-11-26 20:23:46 +0000296 } else if (sys::fs::exists(S)) {
297 Driver->addFile(S);
Rui Ueyama52a15092015-10-11 03:28:42 +0000298 } else {
299 std::string Path = findFromSearchPaths(S);
300 if (Path.empty())
Rui Ueyama025d59b2016-02-02 20:27:59 +0000301 setError("Unable to find " + S);
302 else
303 Driver->addFile(Saver.save(Path));
Rui Ueyama52a15092015-10-11 03:28:42 +0000304 }
305}
306
Rui Ueyama717677a2016-02-11 21:17:59 +0000307void ScriptParser::readAsNeeded() {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000308 expect("(");
Rui Ueyama35da9b62015-10-11 20:59:12 +0000309 bool Orig = Config->AsNeeded;
310 Config->AsNeeded = true;
Rui Ueyama025d59b2016-02-02 20:27:59 +0000311 while (!Error) {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000312 StringRef Tok = next();
313 if (Tok == ")")
Rui Ueyama35da9b62015-10-11 20:59:12 +0000314 break;
Rui Ueyama52a15092015-10-11 03:28:42 +0000315 addFile(Tok);
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000316 }
Rui Ueyama35da9b62015-10-11 20:59:12 +0000317 Config->AsNeeded = Orig;
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000318}
319
Rui Ueyama717677a2016-02-11 21:17:59 +0000320void ScriptParser::readEntry() {
Denis Protivensky90c50992015-10-08 06:48:38 +0000321 // -e <symbol> takes predecence over ENTRY(<symbol>).
322 expect("(");
323 StringRef Tok = next();
324 if (Config->Entry.empty())
325 Config->Entry = Tok;
326 expect(")");
327}
328
Rui Ueyama717677a2016-02-11 21:17:59 +0000329void ScriptParser::readExtern() {
George Rimar83f406c2015-10-19 17:35:12 +0000330 expect("(");
Rui Ueyama025d59b2016-02-02 20:27:59 +0000331 while (!Error) {
George Rimar83f406c2015-10-19 17:35:12 +0000332 StringRef Tok = next();
333 if (Tok == ")")
334 return;
335 Config->Undefined.push_back(Tok);
336 }
337}
338
Rui Ueyama717677a2016-02-11 21:17:59 +0000339void ScriptParser::readGroup() {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000340 expect("(");
Rui Ueyama025d59b2016-02-02 20:27:59 +0000341 while (!Error) {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000342 StringRef Tok = next();
343 if (Tok == ")")
344 return;
345 if (Tok == "AS_NEEDED") {
346 readAsNeeded();
347 continue;
348 }
Rui Ueyama52a15092015-10-11 03:28:42 +0000349 addFile(Tok);
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000350 }
351}
352
Rui Ueyama717677a2016-02-11 21:17:59 +0000353void ScriptParser::readInclude() {
Rui Ueyama31aa1f82015-10-11 01:31:55 +0000354 StringRef Tok = next();
355 auto MBOrErr = MemoryBuffer::getFile(Tok);
Rui Ueyama025d59b2016-02-02 20:27:59 +0000356 if (!MBOrErr) {
357 setError("cannot open " + Tok);
358 return;
359 }
Rui Ueyama31aa1f82015-10-11 01:31:55 +0000360 std::unique_ptr<MemoryBuffer> &MB = *MBOrErr;
Rui Ueyamaa47ee682015-10-11 01:53:04 +0000361 StringRef S = Saver.save(MB->getMemBufferRef().getBuffer());
362 std::vector<StringRef> V = tokenize(S);
Rui Ueyama31aa1f82015-10-11 01:31:55 +0000363 Tokens.insert(Tokens.begin() + Pos, V.begin(), V.end());
Rui Ueyama31aa1f82015-10-11 01:31:55 +0000364}
365
Rui Ueyama717677a2016-02-11 21:17:59 +0000366void ScriptParser::readOutput() {
Rui Ueyamaee592822015-10-07 00:25:09 +0000367 // -o <file> takes predecence over OUTPUT(<file>).
368 expect("(");
369 StringRef Tok = next();
370 if (Config->OutputFile.empty())
371 Config->OutputFile = Tok;
372 expect(")");
373}
374
Rui Ueyama717677a2016-02-11 21:17:59 +0000375void ScriptParser::readOutputArch() {
Davide Italiano9159ce92015-10-12 21:50:08 +0000376 // Error checking only for now.
377 expect("(");
378 next();
379 expect(")");
380}
381
Rui Ueyama717677a2016-02-11 21:17:59 +0000382void ScriptParser::readOutputFormat() {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000383 // Error checking only for now.
384 expect("(");
385 next();
Davide Italiano6836c612015-10-12 21:08:41 +0000386 StringRef Tok = next();
387 if (Tok == ")")
388 return;
Rui Ueyama025d59b2016-02-02 20:27:59 +0000389 if (Tok != ",") {
390 setError("unexpected token: " + Tok);
391 return;
392 }
Davide Italiano6836c612015-10-12 21:08:41 +0000393 next();
394 expect(",");
395 next();
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000396 expect(")");
397}
398
Rui Ueyama717677a2016-02-11 21:17:59 +0000399void ScriptParser::readSearchDir() {
Davide Italiano68a39a62015-10-08 17:51:41 +0000400 expect("(");
Rui Ueyama52a15092015-10-11 03:28:42 +0000401 Config->SearchPaths.push_back(next());
Davide Italiano68a39a62015-10-08 17:51:41 +0000402 expect(")");
403}
404
Rui Ueyama717677a2016-02-11 21:17:59 +0000405void ScriptParser::readSections() {
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000406 expect("{");
Rui Ueyama025d59b2016-02-02 20:27:59 +0000407 while (!Error && !skip("}"))
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000408 readOutputSectionDescription();
409}
410
George Rimar481c2ce2016-02-23 07:47:54 +0000411void ScriptParser::readSectionPatterns(StringRef OutSec, bool Keep) {
412 expect("(");
413 while (!Error && !skip(")"))
414 Script->Sections.emplace_back(OutSec, next(), Keep);
415}
416
George Rimare2ee72b2016-02-26 14:48:31 +0000417std::vector<uint8_t> ScriptParser::parseHex(StringRef S) {
418 std::vector<uint8_t> Hex;
419 while (!S.empty()) {
420 StringRef B = S.substr(0, 2);
421 S = S.substr(2);
422 uint8_t H;
423 if (B.getAsInteger(16, H)) {
424 setError("Not a HEX value: " + B);
425 return {};
426 }
427 Hex.push_back(H);
428 }
429 return Hex;
430}
431
Rui Ueyama717677a2016-02-11 21:17:59 +0000432void ScriptParser::readOutputSectionDescription() {
George Rimare2ee72b2016-02-26 14:48:31 +0000433 OutSection OutSec;
434 OutSec.Name = next();
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000435 expect(":");
436 expect("{");
Rui Ueyama025d59b2016-02-02 20:27:59 +0000437 while (!Error && !skip("}")) {
George Rimar481c2ce2016-02-23 07:47:54 +0000438 StringRef Tok = next();
439 if (Tok == "*") {
George Rimare2ee72b2016-02-26 14:48:31 +0000440 readSectionPatterns(OutSec.Name, false);
George Rimar481c2ce2016-02-23 07:47:54 +0000441 } else if (Tok == "KEEP") {
442 expect("(");
443 next(); // Skip *
George Rimare2ee72b2016-02-26 14:48:31 +0000444 readSectionPatterns(OutSec.Name, true);
George Rimar481c2ce2016-02-23 07:47:54 +0000445 expect(")");
446 } else {
447 setError("Unknown command " + Tok);
448 }
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000449 }
George Rimare2ee72b2016-02-26 14:48:31 +0000450 StringRef Tok = peek();
451 if (Tok.startswith("=")) {
452 if (!Tok.startswith("=0x")) {
453 setError("Filler should be a HEX value");
454 return;
455 }
456 Tok = Tok.substr(3); // Skip '=0x'
457 OutSec.Filler = parseHex(Tok);
458 next();
459 }
460 Script->OutSections.push_back(OutSec);
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000461}
462
Simon Atanasyan16b0cc92015-11-26 05:53:00 +0000463static bool isUnderSysroot(StringRef Path) {
464 if (Config->Sysroot == "")
465 return false;
466 for (; !Path.empty(); Path = sys::path::parent_path(Path))
467 if (sys::fs::equivalent(Config->Sysroot, Path))
468 return true;
469 return false;
470}
471
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000472// Entry point. The other functions or classes are private to this file.
Rui Ueyamaf9de0d62016-02-11 21:38:55 +0000473void LinkerScript::read(MemoryBufferRef MB) {
Simon Atanasyan16b0cc92015-11-26 05:53:00 +0000474 StringRef Path = MB.getBufferIdentifier();
Rui Ueyamaf9de0d62016-02-11 21:38:55 +0000475 ScriptParser(&Alloc, MB.getBuffer(), isUnderSysroot(Path)).run();
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000476}
Rui Ueyama1ebc8ed2016-02-12 21:47:28 +0000477
478template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF32LE> *);
479template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF32BE> *);
480template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF64LE> *);
481template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF64BE> *);
482
483template bool LinkerScript::isDiscarded(InputSectionBase<ELF32LE> *);
484template bool LinkerScript::isDiscarded(InputSectionBase<ELF32BE> *);
485template bool LinkerScript::isDiscarded(InputSectionBase<ELF64LE> *);
486template bool LinkerScript::isDiscarded(InputSectionBase<ELF64BE> *);
487
George Rimar481c2ce2016-02-23 07:47:54 +0000488template bool LinkerScript::shouldKeep(InputSectionBase<ELF32LE> *);
489template bool LinkerScript::shouldKeep(InputSectionBase<ELF32BE> *);
490template bool LinkerScript::shouldKeep(InputSectionBase<ELF64LE> *);
491template bool LinkerScript::shouldKeep(InputSectionBase<ELF64BE> *);