blob: 36c92524166952871065c1756cc5031dfb3b99b5 [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;
Rafael Espindolae0df00b2016-02-28 00:25:54 +000029using namespace lld::elf;
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +000030
Rafael Espindolae0df00b2016-02-28 00:25:54 +000031LinkerScript *elf::Script;
Rui Ueyama717677a2016-02-11 21:17:59 +000032
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) {
Rui Ueyama3e808972016-02-28 05:09:11 +000058 auto I = Filler.find(Name);
59 if (I == Filler.end())
60 return {};
61 return I->second;
George Rimare2ee72b2016-02-26 14:48:31 +000062}
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) {
Rui Ueyama3e808972016-02-28 05:09:11 +000068 auto E = SectionOrder.end();
69 auto I = std::find(SectionOrder.begin(), E, A);
70 auto J = std::find(SectionOrder.begin(), E, B);
71 if (I == E || J == E)
Rui Ueyama717677a2016-02-11 21:17:59 +000072 return 0;
73 return I < J ? -1 : 1;
74}
75
George Rimarcb2aeb62016-02-24 08:49:50 +000076// Returns true if S matches T. S can contain glob meta-characters.
77// The asterisk ('*') matches zero or more characacters, and the question
78// mark ('?') matches one character.
Rui Ueyama1ebc8ed2016-02-12 21:47:28 +000079static bool matchStr(StringRef S, StringRef T) {
80 for (;;) {
81 if (S.empty())
82 return T.empty();
83 if (S[0] == '*') {
84 S = S.substr(1);
85 if (S.empty())
86 // Fast path. If a pattern is '*', it matches anything.
87 return true;
88 for (size_t I = 0, E = T.size(); I < E; ++I)
89 if (matchStr(S, T.substr(I)))
90 return true;
91 return false;
92 }
George Rimarcb2aeb62016-02-24 08:49:50 +000093 if (T.empty() || (S[0] != T[0] && S[0] != '?'))
Rui Ueyama1ebc8ed2016-02-12 21:47:28 +000094 return false;
95 S = S.substr(1);
96 T = T.substr(1);
97 }
98}
99
100template <class ELFT> bool SectionRule::match(InputSectionBase<ELFT> *S) {
101 return matchStr(SectionPattern, S->getSectionName());
102}
103
Rafael Espindolae0df00b2016-02-28 00:25:54 +0000104class elf::ScriptParser {
George Rimarc3794e52016-02-24 09:21:47 +0000105 typedef void (ScriptParser::*Handler)();
106
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000107public:
Rui Ueyama717677a2016-02-11 21:17:59 +0000108 ScriptParser(BumpPtrAllocator *A, StringRef S, bool B)
Rui Ueyama38dc8342016-03-30 16:51:57 +0000109 : Saver(*A), Input(S), Tokens(tokenize(S)), IsUnderSysroot(B) {}
George Rimarf23b2322016-02-19 10:45:45 +0000110
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000111 void run();
112
113private:
Rui Ueyama025d59b2016-02-02 20:27:59 +0000114 void setError(const Twine &Msg);
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000115 static std::vector<StringRef> tokenize(StringRef S);
116 static StringRef skipSpace(StringRef S);
Rui Ueyama025d59b2016-02-02 20:27:59 +0000117 bool atEOF();
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000118 StringRef next();
George Rimare2ee72b2016-02-26 14:48:31 +0000119 StringRef peek();
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000120 bool skip(StringRef Tok);
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000121 void expect(StringRef Expect);
122
Rui Ueyama52a15092015-10-11 03:28:42 +0000123 void addFile(StringRef Path);
124
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000125 void readAsNeeded();
Denis Protivensky90c50992015-10-08 06:48:38 +0000126 void readEntry();
George Rimar83f406c2015-10-19 17:35:12 +0000127 void readExtern();
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000128 void readGroup();
Rui Ueyama31aa1f82015-10-11 01:31:55 +0000129 void readInclude();
George Rimarc3794e52016-02-24 09:21:47 +0000130 void readNothing() {}
Rui Ueyamaee592822015-10-07 00:25:09 +0000131 void readOutput();
Davide Italiano9159ce92015-10-12 21:50:08 +0000132 void readOutputArch();
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000133 void readOutputFormat();
Davide Italiano68a39a62015-10-08 17:51:41 +0000134 void readSearchDir();
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000135 void readSections();
136
137 void readOutputSectionDescription();
George Rimar481c2ce2016-02-23 07:47:54 +0000138 void readSectionPatterns(StringRef OutSec, bool Keep);
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000139
Rui Ueyama38dc8342016-03-30 16:51:57 +0000140 size_t getPos();
George Rimar2348320d2016-04-06 08:08:40 +0000141 void printErrorPos();
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 Ueyama38dc8342016-03-30 16:51:57 +0000145 StringRef Input;
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000146 std::vector<StringRef> Tokens;
George Rimarc3794e52016-02-24 09:21:47 +0000147 const static StringMap<Handler> Cmd;
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000148 size_t Pos = 0;
Simon Atanasyan16b0cc92015-11-26 05:53:00 +0000149 bool IsUnderSysroot;
George Rimarf23b2322016-02-19 10:45:45 +0000150 bool Error = false;
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000151};
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000152
Rafael Espindolae0df00b2016-02-28 00:25:54 +0000153const StringMap<elf::ScriptParser::Handler> elf::ScriptParser::Cmd = {
George Rimarc3794e52016-02-24 09:21:47 +0000154 {"ENTRY", &ScriptParser::readEntry},
155 {"EXTERN", &ScriptParser::readExtern},
156 {"GROUP", &ScriptParser::readGroup},
157 {"INCLUDE", &ScriptParser::readInclude},
158 {"INPUT", &ScriptParser::readGroup},
159 {"OUTPUT", &ScriptParser::readOutput},
160 {"OUTPUT_ARCH", &ScriptParser::readOutputArch},
161 {"OUTPUT_FORMAT", &ScriptParser::readOutputFormat},
162 {"SEARCH_DIR", &ScriptParser::readSearchDir},
163 {"SECTIONS", &ScriptParser::readSections},
164 {";", &ScriptParser::readNothing}};
165
Rui Ueyama717677a2016-02-11 21:17:59 +0000166void ScriptParser::run() {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000167 while (!atEOF()) {
168 StringRef Tok = next();
George Rimarc3794e52016-02-24 09:21:47 +0000169 if (Handler Fn = Cmd.lookup(Tok))
170 (this->*Fn)();
171 else
George Rimar57610422016-03-11 14:43:02 +0000172 setError("unknown directive: " + Tok);
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000173 }
174}
175
George Rimar2348320d2016-04-06 08:08:40 +0000176// Returns the line that the character S[Pos] is in.
177static StringRef getLine(StringRef S, size_t Pos) {
178 size_t Begin = S.rfind('\n', Pos);
179 size_t End = S.find('\n', Pos);
180 Begin = (Begin == StringRef::npos) ? 0 : Begin + 1;
181 if (End == StringRef::npos)
182 End = S.size();
183 // rtrim for DOS-style newlines.
184 return S.substr(Begin, End - Begin).rtrim();
185}
186
187void ScriptParser::printErrorPos() {
188 StringRef Tok = Tokens[Pos == 0 ? 0 : Pos - 1];
189 StringRef Line = getLine(Input, Tok.data() - Input.data());
190 size_t Col = Tok.data() - Line.data();
191 error(Line);
192 error(std::string(Col, ' ') + "^");
193}
194
Rui Ueyama025d59b2016-02-02 20:27:59 +0000195// We don't want to record cascading errors. Keep only the first one.
Rui Ueyama717677a2016-02-11 21:17:59 +0000196void ScriptParser::setError(const Twine &Msg) {
Rui Ueyama025d59b2016-02-02 20:27:59 +0000197 if (Error)
198 return;
Rui Ueyama38dc8342016-03-30 16:51:57 +0000199 error("line " + Twine(getPos()) + ": " + Msg);
George Rimar2348320d2016-04-06 08:08:40 +0000200 printErrorPos();
Rui Ueyama025d59b2016-02-02 20:27:59 +0000201 Error = true;
202}
203
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000204// Split S into linker script tokens.
Rui Ueyama717677a2016-02-11 21:17:59 +0000205std::vector<StringRef> ScriptParser::tokenize(StringRef S) {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000206 std::vector<StringRef> Ret;
207 for (;;) {
208 S = skipSpace(S);
209 if (S.empty())
210 return Ret;
211
212 // Quoted token
213 if (S.startswith("\"")) {
214 size_t E = S.find("\"", 1);
Rui Ueyama025d59b2016-02-02 20:27:59 +0000215 if (E == StringRef::npos) {
George Rimar57610422016-03-11 14:43:02 +0000216 error("unclosed quote");
Rui Ueyama025d59b2016-02-02 20:27:59 +0000217 return {};
218 }
Pete Cooper60259332016-01-22 23:46:37 +0000219 Ret.push_back(S.substr(1, E - 1));
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000220 S = S.substr(E + 1);
221 continue;
222 }
223
224 // Unquoted token
225 size_t Pos = S.find_first_not_of(
226 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
227 "0123456789_.$/\\~=+[]*?-:");
228 // A character that cannot start a word (which is usually a
229 // punctuation) forms a single character token.
230 if (Pos == 0)
231 Pos = 1;
232 Ret.push_back(S.substr(0, Pos));
233 S = S.substr(Pos);
234 }
235}
236
237// Skip leading whitespace characters or /**/-style comments.
Rui Ueyama717677a2016-02-11 21:17:59 +0000238StringRef ScriptParser::skipSpace(StringRef S) {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000239 for (;;) {
240 if (S.startswith("/*")) {
241 size_t E = S.find("*/", 2);
Rui Ueyama025d59b2016-02-02 20:27:59 +0000242 if (E == StringRef::npos) {
George Rimar57610422016-03-11 14:43:02 +0000243 error("unclosed comment in a linker script");
Rui Ueyama025d59b2016-02-02 20:27:59 +0000244 return "";
245 }
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000246 S = S.substr(E + 2);
247 continue;
248 }
249 size_t Size = S.size();
250 S = S.ltrim();
251 if (S.size() == Size)
252 return S;
253 }
254}
255
Rui Ueyama025d59b2016-02-02 20:27:59 +0000256// An errneous token is handled as if it were the last token before EOF.
Rui Ueyama717677a2016-02-11 21:17:59 +0000257bool ScriptParser::atEOF() { return Error || Tokens.size() == Pos; }
Rui Ueyama025d59b2016-02-02 20:27:59 +0000258
Rui Ueyama717677a2016-02-11 21:17:59 +0000259StringRef ScriptParser::next() {
Rui Ueyama025d59b2016-02-02 20:27:59 +0000260 if (Error)
261 return "";
262 if (atEOF()) {
George Rimar57610422016-03-11 14:43:02 +0000263 setError("unexpected EOF");
Rui Ueyama025d59b2016-02-02 20:27:59 +0000264 return "";
265 }
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000266 return Tokens[Pos++];
267}
268
George Rimare2ee72b2016-02-26 14:48:31 +0000269StringRef ScriptParser::peek() {
270 StringRef Tok = next();
271 if (Error)
272 return "";
273 --Pos;
274 return Tok;
275}
276
Rui Ueyama717677a2016-02-11 21:17:59 +0000277bool ScriptParser::skip(StringRef Tok) {
Rui Ueyama025d59b2016-02-02 20:27:59 +0000278 if (Error)
279 return false;
280 if (atEOF()) {
George Rimar57610422016-03-11 14:43:02 +0000281 setError("unexpected EOF");
Rui Ueyama025d59b2016-02-02 20:27:59 +0000282 return false;
283 }
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000284 if (Tok != Tokens[Pos])
285 return false;
286 ++Pos;
287 return true;
288}
289
Rui Ueyama717677a2016-02-11 21:17:59 +0000290void ScriptParser::expect(StringRef Expect) {
Rui Ueyama025d59b2016-02-02 20:27:59 +0000291 if (Error)
292 return;
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000293 StringRef Tok = next();
294 if (Tok != Expect)
Rui Ueyama025d59b2016-02-02 20:27:59 +0000295 setError(Expect + " expected, but got " + Tok);
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000296}
297
Rui Ueyama717677a2016-02-11 21:17:59 +0000298void ScriptParser::addFile(StringRef S) {
Simon Atanasyan16b0cc92015-11-26 05:53:00 +0000299 if (IsUnderSysroot && S.startswith("/")) {
300 SmallString<128> Path;
301 (Config->Sysroot + S).toStringRef(Path);
302 if (sys::fs::exists(Path)) {
303 Driver->addFile(Saver.save(Path.str()));
304 return;
305 }
306 }
307
Rui Ueyamaf03f3cc2015-10-13 00:09:21 +0000308 if (sys::path::is_absolute(S)) {
Rui Ueyama52a15092015-10-11 03:28:42 +0000309 Driver->addFile(S);
310 } else if (S.startswith("=")) {
311 if (Config->Sysroot.empty())
312 Driver->addFile(S.substr(1));
313 else
314 Driver->addFile(Saver.save(Config->Sysroot + "/" + S.substr(1)));
315 } else if (S.startswith("-l")) {
Rui Ueyama21eecb42016-02-02 21:13:09 +0000316 Driver->addLibrary(S.substr(2));
Simon Atanasyana1b8fc32015-11-26 20:23:46 +0000317 } else if (sys::fs::exists(S)) {
318 Driver->addFile(S);
Rui Ueyama52a15092015-10-11 03:28:42 +0000319 } else {
320 std::string Path = findFromSearchPaths(S);
321 if (Path.empty())
George Rimar777f9632016-03-12 08:31:34 +0000322 setError("unable to find " + S);
Rui Ueyama025d59b2016-02-02 20:27:59 +0000323 else
324 Driver->addFile(Saver.save(Path));
Rui Ueyama52a15092015-10-11 03:28:42 +0000325 }
326}
327
Rui Ueyama717677a2016-02-11 21:17:59 +0000328void ScriptParser::readAsNeeded() {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000329 expect("(");
Rui Ueyama35da9b62015-10-11 20:59:12 +0000330 bool Orig = Config->AsNeeded;
331 Config->AsNeeded = true;
Rui Ueyama025d59b2016-02-02 20:27:59 +0000332 while (!Error) {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000333 StringRef Tok = next();
334 if (Tok == ")")
Rui Ueyama35da9b62015-10-11 20:59:12 +0000335 break;
Rui Ueyama52a15092015-10-11 03:28:42 +0000336 addFile(Tok);
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000337 }
Rui Ueyama35da9b62015-10-11 20:59:12 +0000338 Config->AsNeeded = Orig;
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000339}
340
Rui Ueyama717677a2016-02-11 21:17:59 +0000341void ScriptParser::readEntry() {
Denis Protivensky90c50992015-10-08 06:48:38 +0000342 // -e <symbol> takes predecence over ENTRY(<symbol>).
343 expect("(");
344 StringRef Tok = next();
345 if (Config->Entry.empty())
346 Config->Entry = Tok;
347 expect(")");
348}
349
Rui Ueyama717677a2016-02-11 21:17:59 +0000350void ScriptParser::readExtern() {
George Rimar83f406c2015-10-19 17:35:12 +0000351 expect("(");
Rui Ueyama025d59b2016-02-02 20:27:59 +0000352 while (!Error) {
George Rimar83f406c2015-10-19 17:35:12 +0000353 StringRef Tok = next();
354 if (Tok == ")")
355 return;
356 Config->Undefined.push_back(Tok);
357 }
358}
359
Rui Ueyama717677a2016-02-11 21:17:59 +0000360void ScriptParser::readGroup() {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000361 expect("(");
Rui Ueyama025d59b2016-02-02 20:27:59 +0000362 while (!Error) {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000363 StringRef Tok = next();
364 if (Tok == ")")
365 return;
366 if (Tok == "AS_NEEDED") {
367 readAsNeeded();
368 continue;
369 }
Rui Ueyama52a15092015-10-11 03:28:42 +0000370 addFile(Tok);
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000371 }
372}
373
Rui Ueyama717677a2016-02-11 21:17:59 +0000374void ScriptParser::readInclude() {
Rui Ueyama31aa1f82015-10-11 01:31:55 +0000375 StringRef Tok = next();
376 auto MBOrErr = MemoryBuffer::getFile(Tok);
Rui Ueyama025d59b2016-02-02 20:27:59 +0000377 if (!MBOrErr) {
George Rimar57610422016-03-11 14:43:02 +0000378 setError("cannot open " + Tok);
Rui Ueyama025d59b2016-02-02 20:27:59 +0000379 return;
380 }
Rui Ueyama31aa1f82015-10-11 01:31:55 +0000381 std::unique_ptr<MemoryBuffer> &MB = *MBOrErr;
Rui Ueyamaa47ee682015-10-11 01:53:04 +0000382 StringRef S = Saver.save(MB->getMemBufferRef().getBuffer());
383 std::vector<StringRef> V = tokenize(S);
Rui Ueyama31aa1f82015-10-11 01:31:55 +0000384 Tokens.insert(Tokens.begin() + Pos, V.begin(), V.end());
Rui Ueyama31aa1f82015-10-11 01:31:55 +0000385}
386
Rui Ueyama717677a2016-02-11 21:17:59 +0000387void ScriptParser::readOutput() {
Rui Ueyamaee592822015-10-07 00:25:09 +0000388 // -o <file> takes predecence over OUTPUT(<file>).
389 expect("(");
390 StringRef Tok = next();
391 if (Config->OutputFile.empty())
392 Config->OutputFile = Tok;
393 expect(")");
394}
395
Rui Ueyama717677a2016-02-11 21:17:59 +0000396void ScriptParser::readOutputArch() {
Davide Italiano9159ce92015-10-12 21:50:08 +0000397 // Error checking only for now.
398 expect("(");
399 next();
400 expect(")");
401}
402
Rui Ueyama717677a2016-02-11 21:17:59 +0000403void ScriptParser::readOutputFormat() {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000404 // Error checking only for now.
405 expect("(");
406 next();
Davide Italiano6836c612015-10-12 21:08:41 +0000407 StringRef Tok = next();
408 if (Tok == ")")
409 return;
Rui Ueyama025d59b2016-02-02 20:27:59 +0000410 if (Tok != ",") {
George Rimar57610422016-03-11 14:43:02 +0000411 setError("unexpected token: " + Tok);
Rui Ueyama025d59b2016-02-02 20:27:59 +0000412 return;
413 }
Davide Italiano6836c612015-10-12 21:08:41 +0000414 next();
415 expect(",");
416 next();
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000417 expect(")");
418}
419
Rui Ueyama717677a2016-02-11 21:17:59 +0000420void ScriptParser::readSearchDir() {
Davide Italiano68a39a62015-10-08 17:51:41 +0000421 expect("(");
Rafael Espindola06501922016-03-08 17:13:12 +0000422 Config->SearchPaths.push_back(next());
Davide Italiano68a39a62015-10-08 17:51:41 +0000423 expect(")");
424}
425
Rui Ueyama717677a2016-02-11 21:17:59 +0000426void ScriptParser::readSections() {
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000427 expect("{");
Rui Ueyama025d59b2016-02-02 20:27:59 +0000428 while (!Error && !skip("}"))
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000429 readOutputSectionDescription();
430}
431
George Rimar481c2ce2016-02-23 07:47:54 +0000432void ScriptParser::readSectionPatterns(StringRef OutSec, bool Keep) {
433 expect("(");
434 while (!Error && !skip(")"))
435 Script->Sections.emplace_back(OutSec, next(), Keep);
436}
437
Rui Ueyama38dc8342016-03-30 16:51:57 +0000438// Returns the current line number.
439size_t ScriptParser::getPos() {
440 if (Pos == 0)
441 return 1;
442 const char *Begin = Input.data();
443 const char *Tok = Tokens[Pos - 1].data();
444 return StringRef(Begin, Tok - Begin).count('\n') + 1;
445}
446
George Rimare2ee72b2016-02-26 14:48:31 +0000447std::vector<uint8_t> ScriptParser::parseHex(StringRef S) {
448 std::vector<uint8_t> Hex;
449 while (!S.empty()) {
450 StringRef B = S.substr(0, 2);
451 S = S.substr(2);
452 uint8_t H;
453 if (B.getAsInteger(16, H)) {
Rui Ueyama3ed2f062016-03-13 03:17:44 +0000454 setError("not a hexadecimal value: " + B);
George Rimare2ee72b2016-02-26 14:48:31 +0000455 return {};
456 }
457 Hex.push_back(H);
458 }
459 return Hex;
460}
461
Rui Ueyama717677a2016-02-11 21:17:59 +0000462void ScriptParser::readOutputSectionDescription() {
Rui Ueyama3e808972016-02-28 05:09:11 +0000463 StringRef OutSec = next();
464 Script->SectionOrder.push_back(OutSec);
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000465 expect(":");
466 expect("{");
Rui Ueyama025d59b2016-02-02 20:27:59 +0000467 while (!Error && !skip("}")) {
George Rimar481c2ce2016-02-23 07:47:54 +0000468 StringRef Tok = next();
469 if (Tok == "*") {
Rui Ueyama3e808972016-02-28 05:09:11 +0000470 readSectionPatterns(OutSec, false);
George Rimar481c2ce2016-02-23 07:47:54 +0000471 } else if (Tok == "KEEP") {
472 expect("(");
473 next(); // Skip *
Rui Ueyama3e808972016-02-28 05:09:11 +0000474 readSectionPatterns(OutSec, true);
George Rimar481c2ce2016-02-23 07:47:54 +0000475 expect(")");
476 } else {
George Rimar777f9632016-03-12 08:31:34 +0000477 setError("unknown command " + Tok);
George Rimar481c2ce2016-02-23 07:47:54 +0000478 }
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000479 }
George Rimare2ee72b2016-02-26 14:48:31 +0000480 StringRef Tok = peek();
481 if (Tok.startswith("=")) {
482 if (!Tok.startswith("=0x")) {
Rui Ueyama3ed2f062016-03-13 03:17:44 +0000483 setError("filler should be a hexadecimal value");
George Rimare2ee72b2016-02-26 14:48:31 +0000484 return;
485 }
Rui Ueyama3e808972016-02-28 05:09:11 +0000486 Tok = Tok.substr(3);
487 Script->Filler[OutSec] = parseHex(Tok);
George Rimare2ee72b2016-02-26 14:48:31 +0000488 next();
489 }
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000490}
491
Simon Atanasyan16b0cc92015-11-26 05:53:00 +0000492static bool isUnderSysroot(StringRef Path) {
493 if (Config->Sysroot == "")
494 return false;
495 for (; !Path.empty(); Path = sys::path::parent_path(Path))
496 if (sys::fs::equivalent(Config->Sysroot, Path))
497 return true;
498 return false;
499}
500
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000501// Entry point. The other functions or classes are private to this file.
Rui Ueyamaf9de0d62016-02-11 21:38:55 +0000502void LinkerScript::read(MemoryBufferRef MB) {
Simon Atanasyan16b0cc92015-11-26 05:53:00 +0000503 StringRef Path = MB.getBufferIdentifier();
Rui Ueyamaf9de0d62016-02-11 21:38:55 +0000504 ScriptParser(&Alloc, MB.getBuffer(), isUnderSysroot(Path)).run();
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000505}
Rui Ueyama1ebc8ed2016-02-12 21:47:28 +0000506
507template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF32LE> *);
508template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF32BE> *);
509template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF64LE> *);
510template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF64BE> *);
511
512template bool LinkerScript::isDiscarded(InputSectionBase<ELF32LE> *);
513template bool LinkerScript::isDiscarded(InputSectionBase<ELF32BE> *);
514template bool LinkerScript::isDiscarded(InputSectionBase<ELF64LE> *);
515template bool LinkerScript::isDiscarded(InputSectionBase<ELF64BE> *);
516
George Rimar481c2ce2016-02-23 07:47:54 +0000517template bool LinkerScript::shouldKeep(InputSectionBase<ELF32LE> *);
518template bool LinkerScript::shouldKeep(InputSectionBase<ELF32BE> *);
519template bool LinkerScript::shouldKeep(InputSectionBase<ELF64LE> *);
520template bool LinkerScript::shouldKeep(InputSectionBase<ELF64BE> *);