blob: b4580b5fe7c6c347cad6b941e0ca0a2c3a9d42f6 [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)
George Rimarc3794e52016-02-24 09:21:47 +0000109 : Saver(*A), 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
George Rimare2ee72b2016-02-26 14:48:31 +0000140 std::vector<uint8_t> parseHex(StringRef S);
141
Rui Ueyamaa47ee682015-10-11 01:53:04 +0000142 StringSaver Saver;
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000143 std::vector<StringRef> Tokens;
George Rimarc3794e52016-02-24 09:21:47 +0000144 const static StringMap<Handler> Cmd;
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000145 size_t Pos = 0;
Simon Atanasyan16b0cc92015-11-26 05:53:00 +0000146 bool IsUnderSysroot;
George Rimarf23b2322016-02-19 10:45:45 +0000147 bool Error = false;
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000148};
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000149
Rafael Espindolae0df00b2016-02-28 00:25:54 +0000150const StringMap<elf::ScriptParser::Handler> elf::ScriptParser::Cmd = {
George Rimarc3794e52016-02-24 09:21:47 +0000151 {"ENTRY", &ScriptParser::readEntry},
152 {"EXTERN", &ScriptParser::readExtern},
153 {"GROUP", &ScriptParser::readGroup},
154 {"INCLUDE", &ScriptParser::readInclude},
155 {"INPUT", &ScriptParser::readGroup},
156 {"OUTPUT", &ScriptParser::readOutput},
157 {"OUTPUT_ARCH", &ScriptParser::readOutputArch},
158 {"OUTPUT_FORMAT", &ScriptParser::readOutputFormat},
159 {"SEARCH_DIR", &ScriptParser::readSearchDir},
160 {"SECTIONS", &ScriptParser::readSections},
161 {";", &ScriptParser::readNothing}};
162
Rui Ueyama717677a2016-02-11 21:17:59 +0000163void ScriptParser::run() {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000164 while (!atEOF()) {
165 StringRef Tok = next();
George Rimarc3794e52016-02-24 09:21:47 +0000166 if (Handler Fn = Cmd.lookup(Tok))
167 (this->*Fn)();
168 else
George Rimar57610422016-03-11 14:43:02 +0000169 setError("unknown directive: " + Tok);
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000170 }
171}
172
Rui Ueyama025d59b2016-02-02 20:27:59 +0000173// We don't want to record cascading errors. Keep only the first one.
Rui Ueyama717677a2016-02-11 21:17:59 +0000174void ScriptParser::setError(const Twine &Msg) {
Rui Ueyama025d59b2016-02-02 20:27:59 +0000175 if (Error)
176 return;
177 error(Msg);
178 Error = true;
179}
180
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000181// Split S into linker script tokens.
Rui Ueyama717677a2016-02-11 21:17:59 +0000182std::vector<StringRef> ScriptParser::tokenize(StringRef S) {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000183 std::vector<StringRef> Ret;
184 for (;;) {
185 S = skipSpace(S);
186 if (S.empty())
187 return Ret;
188
189 // Quoted token
190 if (S.startswith("\"")) {
191 size_t E = S.find("\"", 1);
Rui Ueyama025d59b2016-02-02 20:27:59 +0000192 if (E == StringRef::npos) {
George Rimar57610422016-03-11 14:43:02 +0000193 error("unclosed quote");
Rui Ueyama025d59b2016-02-02 20:27:59 +0000194 return {};
195 }
Pete Cooper60259332016-01-22 23:46:37 +0000196 Ret.push_back(S.substr(1, E - 1));
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000197 S = S.substr(E + 1);
198 continue;
199 }
200
201 // Unquoted token
202 size_t Pos = S.find_first_not_of(
203 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
204 "0123456789_.$/\\~=+[]*?-:");
205 // A character that cannot start a word (which is usually a
206 // punctuation) forms a single character token.
207 if (Pos == 0)
208 Pos = 1;
209 Ret.push_back(S.substr(0, Pos));
210 S = S.substr(Pos);
211 }
212}
213
214// Skip leading whitespace characters or /**/-style comments.
Rui Ueyama717677a2016-02-11 21:17:59 +0000215StringRef ScriptParser::skipSpace(StringRef S) {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000216 for (;;) {
217 if (S.startswith("/*")) {
218 size_t E = S.find("*/", 2);
Rui Ueyama025d59b2016-02-02 20:27:59 +0000219 if (E == StringRef::npos) {
George Rimar57610422016-03-11 14:43:02 +0000220 error("unclosed comment in a linker script");
Rui Ueyama025d59b2016-02-02 20:27:59 +0000221 return "";
222 }
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000223 S = S.substr(E + 2);
224 continue;
225 }
226 size_t Size = S.size();
227 S = S.ltrim();
228 if (S.size() == Size)
229 return S;
230 }
231}
232
Rui Ueyama025d59b2016-02-02 20:27:59 +0000233// An errneous token is handled as if it were the last token before EOF.
Rui Ueyama717677a2016-02-11 21:17:59 +0000234bool ScriptParser::atEOF() { return Error || Tokens.size() == Pos; }
Rui Ueyama025d59b2016-02-02 20:27:59 +0000235
Rui Ueyama717677a2016-02-11 21:17:59 +0000236StringRef ScriptParser::next() {
Rui Ueyama025d59b2016-02-02 20:27:59 +0000237 if (Error)
238 return "";
239 if (atEOF()) {
George Rimar57610422016-03-11 14:43:02 +0000240 setError("unexpected EOF");
Rui Ueyama025d59b2016-02-02 20:27:59 +0000241 return "";
242 }
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000243 return Tokens[Pos++];
244}
245
George Rimare2ee72b2016-02-26 14:48:31 +0000246StringRef ScriptParser::peek() {
247 StringRef Tok = next();
248 if (Error)
249 return "";
250 --Pos;
251 return Tok;
252}
253
Rui Ueyama717677a2016-02-11 21:17:59 +0000254bool ScriptParser::skip(StringRef Tok) {
Rui Ueyama025d59b2016-02-02 20:27:59 +0000255 if (Error)
256 return false;
257 if (atEOF()) {
George Rimar57610422016-03-11 14:43:02 +0000258 setError("unexpected EOF");
Rui Ueyama025d59b2016-02-02 20:27:59 +0000259 return false;
260 }
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000261 if (Tok != Tokens[Pos])
262 return false;
263 ++Pos;
264 return true;
265}
266
Rui Ueyama717677a2016-02-11 21:17:59 +0000267void ScriptParser::expect(StringRef Expect) {
Rui Ueyama025d59b2016-02-02 20:27:59 +0000268 if (Error)
269 return;
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000270 StringRef Tok = next();
271 if (Tok != Expect)
Rui Ueyama025d59b2016-02-02 20:27:59 +0000272 setError(Expect + " expected, but got " + Tok);
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000273}
274
Rui Ueyama717677a2016-02-11 21:17:59 +0000275void ScriptParser::addFile(StringRef S) {
Simon Atanasyan16b0cc92015-11-26 05:53:00 +0000276 if (IsUnderSysroot && S.startswith("/")) {
277 SmallString<128> Path;
278 (Config->Sysroot + S).toStringRef(Path);
279 if (sys::fs::exists(Path)) {
280 Driver->addFile(Saver.save(Path.str()));
281 return;
282 }
283 }
284
Rui Ueyamaf03f3cc2015-10-13 00:09:21 +0000285 if (sys::path::is_absolute(S)) {
Rui Ueyama52a15092015-10-11 03:28:42 +0000286 Driver->addFile(S);
287 } else if (S.startswith("=")) {
288 if (Config->Sysroot.empty())
289 Driver->addFile(S.substr(1));
290 else
291 Driver->addFile(Saver.save(Config->Sysroot + "/" + S.substr(1)));
292 } else if (S.startswith("-l")) {
Rui Ueyama21eecb42016-02-02 21:13:09 +0000293 Driver->addLibrary(S.substr(2));
Simon Atanasyana1b8fc32015-11-26 20:23:46 +0000294 } else if (sys::fs::exists(S)) {
295 Driver->addFile(S);
Rui Ueyama52a15092015-10-11 03:28:42 +0000296 } else {
297 std::string Path = findFromSearchPaths(S);
298 if (Path.empty())
Rui Ueyama025d59b2016-02-02 20:27:59 +0000299 setError("Unable to find " + S);
300 else
301 Driver->addFile(Saver.save(Path));
Rui Ueyama52a15092015-10-11 03:28:42 +0000302 }
303}
304
Rui Ueyama717677a2016-02-11 21:17:59 +0000305void ScriptParser::readAsNeeded() {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000306 expect("(");
Rui Ueyama35da9b62015-10-11 20:59:12 +0000307 bool Orig = Config->AsNeeded;
308 Config->AsNeeded = true;
Rui Ueyama025d59b2016-02-02 20:27:59 +0000309 while (!Error) {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000310 StringRef Tok = next();
311 if (Tok == ")")
Rui Ueyama35da9b62015-10-11 20:59:12 +0000312 break;
Rui Ueyama52a15092015-10-11 03:28:42 +0000313 addFile(Tok);
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000314 }
Rui Ueyama35da9b62015-10-11 20:59:12 +0000315 Config->AsNeeded = Orig;
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000316}
317
Rui Ueyama717677a2016-02-11 21:17:59 +0000318void ScriptParser::readEntry() {
Denis Protivensky90c50992015-10-08 06:48:38 +0000319 // -e <symbol> takes predecence over ENTRY(<symbol>).
320 expect("(");
321 StringRef Tok = next();
322 if (Config->Entry.empty())
323 Config->Entry = Tok;
324 expect(")");
325}
326
Rui Ueyama717677a2016-02-11 21:17:59 +0000327void ScriptParser::readExtern() {
George Rimar83f406c2015-10-19 17:35:12 +0000328 expect("(");
Rui Ueyama025d59b2016-02-02 20:27:59 +0000329 while (!Error) {
George Rimar83f406c2015-10-19 17:35:12 +0000330 StringRef Tok = next();
331 if (Tok == ")")
332 return;
333 Config->Undefined.push_back(Tok);
334 }
335}
336
Rui Ueyama717677a2016-02-11 21:17:59 +0000337void ScriptParser::readGroup() {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000338 expect("(");
Rui Ueyama025d59b2016-02-02 20:27:59 +0000339 while (!Error) {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000340 StringRef Tok = next();
341 if (Tok == ")")
342 return;
343 if (Tok == "AS_NEEDED") {
344 readAsNeeded();
345 continue;
346 }
Rui Ueyama52a15092015-10-11 03:28:42 +0000347 addFile(Tok);
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000348 }
349}
350
Rui Ueyama717677a2016-02-11 21:17:59 +0000351void ScriptParser::readInclude() {
Rui Ueyama31aa1f82015-10-11 01:31:55 +0000352 StringRef Tok = next();
353 auto MBOrErr = MemoryBuffer::getFile(Tok);
Rui Ueyama025d59b2016-02-02 20:27:59 +0000354 if (!MBOrErr) {
George Rimar57610422016-03-11 14:43:02 +0000355 setError("cannot open " + Tok);
Rui Ueyama025d59b2016-02-02 20:27:59 +0000356 return;
357 }
Rui Ueyama31aa1f82015-10-11 01:31:55 +0000358 std::unique_ptr<MemoryBuffer> &MB = *MBOrErr;
Rui Ueyamaa47ee682015-10-11 01:53:04 +0000359 StringRef S = Saver.save(MB->getMemBufferRef().getBuffer());
360 std::vector<StringRef> V = tokenize(S);
Rui Ueyama31aa1f82015-10-11 01:31:55 +0000361 Tokens.insert(Tokens.begin() + Pos, V.begin(), V.end());
Rui Ueyama31aa1f82015-10-11 01:31:55 +0000362}
363
Rui Ueyama717677a2016-02-11 21:17:59 +0000364void ScriptParser::readOutput() {
Rui Ueyamaee592822015-10-07 00:25:09 +0000365 // -o <file> takes predecence over OUTPUT(<file>).
366 expect("(");
367 StringRef Tok = next();
368 if (Config->OutputFile.empty())
369 Config->OutputFile = Tok;
370 expect(")");
371}
372
Rui Ueyama717677a2016-02-11 21:17:59 +0000373void ScriptParser::readOutputArch() {
Davide Italiano9159ce92015-10-12 21:50:08 +0000374 // Error checking only for now.
375 expect("(");
376 next();
377 expect(")");
378}
379
Rui Ueyama717677a2016-02-11 21:17:59 +0000380void ScriptParser::readOutputFormat() {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000381 // Error checking only for now.
382 expect("(");
383 next();
Davide Italiano6836c612015-10-12 21:08:41 +0000384 StringRef Tok = next();
385 if (Tok == ")")
386 return;
Rui Ueyama025d59b2016-02-02 20:27:59 +0000387 if (Tok != ",") {
George Rimar57610422016-03-11 14:43:02 +0000388 setError("unexpected token: " + Tok);
Rui Ueyama025d59b2016-02-02 20:27:59 +0000389 return;
390 }
Davide Italiano6836c612015-10-12 21:08:41 +0000391 next();
392 expect(",");
393 next();
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000394 expect(")");
395}
396
Rui Ueyama717677a2016-02-11 21:17:59 +0000397void ScriptParser::readSearchDir() {
Davide Italiano68a39a62015-10-08 17:51:41 +0000398 expect("(");
Rafael Espindola06501922016-03-08 17:13:12 +0000399 Config->SearchPaths.push_back(next());
Davide Italiano68a39a62015-10-08 17:51:41 +0000400 expect(")");
401}
402
Rui Ueyama717677a2016-02-11 21:17:59 +0000403void ScriptParser::readSections() {
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000404 expect("{");
Rui Ueyama025d59b2016-02-02 20:27:59 +0000405 while (!Error && !skip("}"))
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000406 readOutputSectionDescription();
407}
408
George Rimar481c2ce2016-02-23 07:47:54 +0000409void ScriptParser::readSectionPatterns(StringRef OutSec, bool Keep) {
410 expect("(");
411 while (!Error && !skip(")"))
412 Script->Sections.emplace_back(OutSec, next(), Keep);
413}
414
George Rimare2ee72b2016-02-26 14:48:31 +0000415std::vector<uint8_t> ScriptParser::parseHex(StringRef S) {
416 std::vector<uint8_t> Hex;
417 while (!S.empty()) {
418 StringRef B = S.substr(0, 2);
419 S = S.substr(2);
420 uint8_t H;
421 if (B.getAsInteger(16, H)) {
422 setError("Not a HEX value: " + B);
423 return {};
424 }
425 Hex.push_back(H);
426 }
427 return Hex;
428}
429
Rui Ueyama717677a2016-02-11 21:17:59 +0000430void ScriptParser::readOutputSectionDescription() {
Rui Ueyama3e808972016-02-28 05:09:11 +0000431 StringRef OutSec = next();
432 Script->SectionOrder.push_back(OutSec);
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000433 expect(":");
434 expect("{");
Rui Ueyama025d59b2016-02-02 20:27:59 +0000435 while (!Error && !skip("}")) {
George Rimar481c2ce2016-02-23 07:47:54 +0000436 StringRef Tok = next();
437 if (Tok == "*") {
Rui Ueyama3e808972016-02-28 05:09:11 +0000438 readSectionPatterns(OutSec, false);
George Rimar481c2ce2016-02-23 07:47:54 +0000439 } else if (Tok == "KEEP") {
440 expect("(");
441 next(); // Skip *
Rui Ueyama3e808972016-02-28 05:09:11 +0000442 readSectionPatterns(OutSec, true);
George Rimar481c2ce2016-02-23 07:47:54 +0000443 expect(")");
444 } else {
445 setError("Unknown command " + Tok);
446 }
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000447 }
George Rimare2ee72b2016-02-26 14:48:31 +0000448 StringRef Tok = peek();
449 if (Tok.startswith("=")) {
450 if (!Tok.startswith("=0x")) {
451 setError("Filler should be a HEX value");
452 return;
453 }
Rui Ueyama3e808972016-02-28 05:09:11 +0000454 Tok = Tok.substr(3);
455 Script->Filler[OutSec] = parseHex(Tok);
George Rimare2ee72b2016-02-26 14:48:31 +0000456 next();
457 }
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000458}
459
Simon Atanasyan16b0cc92015-11-26 05:53:00 +0000460static bool isUnderSysroot(StringRef Path) {
461 if (Config->Sysroot == "")
462 return false;
463 for (; !Path.empty(); Path = sys::path::parent_path(Path))
464 if (sys::fs::equivalent(Config->Sysroot, Path))
465 return true;
466 return false;
467}
468
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000469// Entry point. The other functions or classes are private to this file.
Rui Ueyamaf9de0d62016-02-11 21:38:55 +0000470void LinkerScript::read(MemoryBufferRef MB) {
Simon Atanasyan16b0cc92015-11-26 05:53:00 +0000471 StringRef Path = MB.getBufferIdentifier();
Rui Ueyamaf9de0d62016-02-11 21:38:55 +0000472 ScriptParser(&Alloc, MB.getBuffer(), isUnderSysroot(Path)).run();
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000473}
Rui Ueyama1ebc8ed2016-02-12 21:47:28 +0000474
475template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF32LE> *);
476template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF32BE> *);
477template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF64LE> *);
478template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF64BE> *);
479
480template bool LinkerScript::isDiscarded(InputSectionBase<ELF32LE> *);
481template bool LinkerScript::isDiscarded(InputSectionBase<ELF32BE> *);
482template bool LinkerScript::isDiscarded(InputSectionBase<ELF64LE> *);
483template bool LinkerScript::isDiscarded(InputSectionBase<ELF64BE> *);
484
George Rimar481c2ce2016-02-23 07:47:54 +0000485template bool LinkerScript::shouldKeep(InputSectionBase<ELF32LE> *);
486template bool LinkerScript::shouldKeep(InputSectionBase<ELF32BE> *);
487template bool LinkerScript::shouldKeep(InputSectionBase<ELF64LE> *);
488template bool LinkerScript::shouldKeep(InputSectionBase<ELF64BE> *);