blob: fec2e197ee7f9a348e62d7fc39cae3c7cb299c24 [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"
George Rimar652852c2016-04-16 10:10:32 +000020#include "OutputSections.h"
Adhemerval Zanellae77b5bf2016-04-06 20:59:11 +000021#include "ScriptParser.h"
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +000022#include "SymbolTable.h"
George Rimar652852c2016-04-16 10:10:32 +000023#include "llvm/Support/ELF.h"
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +000024#include "llvm/Support/FileSystem.h"
25#include "llvm/Support/MemoryBuffer.h"
Rui Ueyamaf03f3cc2015-10-13 00:09:21 +000026#include "llvm/Support/Path.h"
Rui Ueyamaa47ee682015-10-11 01:53:04 +000027#include "llvm/Support/StringSaver.h"
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +000028
29using namespace llvm;
George Rimar652852c2016-04-16 10:10:32 +000030using namespace llvm::ELF;
Rui Ueyama1ebc8ed2016-02-12 21:47:28 +000031using namespace llvm::object;
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +000032using namespace lld;
Rafael Espindolae0df00b2016-02-28 00:25:54 +000033using namespace lld::elf;
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +000034
Rafael Espindolae0df00b2016-02-28 00:25:54 +000035LinkerScript *elf::Script;
Rui Ueyama717677a2016-02-11 21:17:59 +000036
George Rimar652852c2016-04-16 10:10:32 +000037static uint64_t getInteger(StringRef S) {
38 uint64_t V;
39 if (S.getAsInteger(0, V)) {
40 error("malformed number: " + S);
41 return 0;
42 }
43 return V;
44}
45
46// Evaluates the expression given by list of tokens.
47uint64_t LinkerScript::evaluate(std::vector<StringRef> &Tokens,
48 uint64_t LocCounter) {
49 uint64_t Result = 0;
50 for (size_t I = 0, E = Tokens.size(); I < E; ++I) {
51 // Each second token should be '+' as this is the
52 // only operator we support now.
53 if (I % 2 == 1) {
54 if (Tokens[I] == "+")
55 continue;
56 error("error in location counter expression");
57 return 0;
58 }
59
60 StringRef Tok = Tokens[I];
61 if (Tok == ".")
62 Result += LocCounter;
63 else
64 Result += getInteger(Tok);
65 }
66 return Result;
67}
68
Rui Ueyama1ebc8ed2016-02-12 21:47:28 +000069template <class ELFT>
George Rimar481c2ce2016-02-23 07:47:54 +000070SectionRule *LinkerScript::find(InputSectionBase<ELFT> *S) {
Rui Ueyama1ebc8ed2016-02-12 21:47:28 +000071 for (SectionRule &R : Sections)
72 if (R.match(S))
George Rimar481c2ce2016-02-23 07:47:54 +000073 return &R;
74 return nullptr;
75}
76
77template <class ELFT>
78StringRef LinkerScript::getOutputSection(InputSectionBase<ELFT> *S) {
79 SectionRule *R = find(S);
80 return R ? R->Dest : "";
Rui Ueyama717677a2016-02-11 21:17:59 +000081}
82
Rui Ueyama1ebc8ed2016-02-12 21:47:28 +000083template <class ELFT>
84bool LinkerScript::isDiscarded(InputSectionBase<ELFT> *S) {
85 return getOutputSection(S) == "/DISCARD/";
Rui Ueyama717677a2016-02-11 21:17:59 +000086}
87
George Rimar481c2ce2016-02-23 07:47:54 +000088template <class ELFT> bool LinkerScript::shouldKeep(InputSectionBase<ELFT> *S) {
89 SectionRule *R = find(S);
90 return R && R->Keep;
91}
92
George Rimar652852c2016-04-16 10:10:32 +000093// This method finalizes the Locations list. Adds neccesary locations for
94// orphan sections, what prepares it for futher use without
95// changes in LinkerScript::assignAddresses().
96template <class ELFT>
97void LinkerScript::fixupLocations(std::vector<OutputSectionBase<ELFT> *> &S) {
98 // Orphan sections are sections present in the input files which
99 // are not explicitly placed into the output file by the linker
100 // script. We place orphan sections at end of file. Other linkers places
101 // them using some heuristics as described in
102 // https://sourceware.org/binutils/docs/ld/Orphan-Sections.html#Orphan-Sections.
103 for (OutputSectionBase<ELFT> *Sec : S) {
104 StringRef Name = Sec->getName();
105 auto I = std::find(SectionOrder.begin(), SectionOrder.end(), Name);
106 if (I == SectionOrder.end())
107 Locations.push_back({Command::Section, {}, {Name}});
108 }
109}
110
111template <class ELFT>
112void LinkerScript::assignAddresses(std::vector<OutputSectionBase<ELFT> *> &S) {
113 typedef typename ELFT::uint uintX_t;
114
115 Script->fixupLocations(S);
116
117 uintX_t ThreadBssOffset = 0;
118 uintX_t VA =
119 Out<ELFT>::ElfHeader->getSize() + Out<ELFT>::ProgramHeaders->getSize();
120
121 for (LocationNode &Node : Locations) {
122 if (Node.Type == Command::Expr) {
123 VA = evaluate(Node.Expr, VA);
124 continue;
125 }
126
127 auto I =
128 std::find_if(S.begin(), S.end(), [&](OutputSectionBase<ELFT> *Sec) {
129 return Sec->getName() == Node.SectionName;
130 });
131 if (I == S.end())
132 continue;
133
134 OutputSectionBase<ELFT> *Sec = *I;
135 uintX_t Align = Sec->getAlign();
136 if ((Sec->getFlags() & SHF_TLS) && Sec->getType() == SHT_NOBITS) {
137 uintX_t TVA = VA + ThreadBssOffset;
138 TVA = alignTo(TVA, Align);
139 Sec->setVA(TVA);
140 ThreadBssOffset = TVA - VA + Sec->getSize();
141 continue;
142 }
143
144 if (Sec->getFlags() & SHF_ALLOC) {
145 VA = alignTo(VA, Align);
146 Sec->setVA(VA);
147 VA += Sec->getSize();
148 continue;
149 }
150 }
151}
152
George Rimare2ee72b2016-02-26 14:48:31 +0000153ArrayRef<uint8_t> LinkerScript::getFiller(StringRef Name) {
Rui Ueyama3e808972016-02-28 05:09:11 +0000154 auto I = Filler.find(Name);
155 if (I == Filler.end())
156 return {};
157 return I->second;
George Rimare2ee72b2016-02-26 14:48:31 +0000158}
159
Rui Ueyamae9c58062016-02-12 20:41:43 +0000160// A compartor to sort output sections. Returns -1 or 1 if both
161// A and B are mentioned in linker scripts. Otherwise, returns 0
162// to use the default rule which is implemented in Writer.cpp.
Rui Ueyama717677a2016-02-11 21:17:59 +0000163int LinkerScript::compareSections(StringRef A, StringRef B) {
Rui Ueyama3e808972016-02-28 05:09:11 +0000164 auto E = SectionOrder.end();
165 auto I = std::find(SectionOrder.begin(), E, A);
166 auto J = std::find(SectionOrder.begin(), E, B);
167 if (I == E || J == E)
Rui Ueyama717677a2016-02-11 21:17:59 +0000168 return 0;
169 return I < J ? -1 : 1;
170}
171
George Rimarcb2aeb62016-02-24 08:49:50 +0000172// Returns true if S matches T. S can contain glob meta-characters.
173// The asterisk ('*') matches zero or more characacters, and the question
174// mark ('?') matches one character.
Rui Ueyama1ebc8ed2016-02-12 21:47:28 +0000175static bool matchStr(StringRef S, StringRef T) {
176 for (;;) {
177 if (S.empty())
178 return T.empty();
179 if (S[0] == '*') {
180 S = S.substr(1);
181 if (S.empty())
182 // Fast path. If a pattern is '*', it matches anything.
183 return true;
184 for (size_t I = 0, E = T.size(); I < E; ++I)
185 if (matchStr(S, T.substr(I)))
186 return true;
187 return false;
188 }
George Rimarcb2aeb62016-02-24 08:49:50 +0000189 if (T.empty() || (S[0] != T[0] && S[0] != '?'))
Rui Ueyama1ebc8ed2016-02-12 21:47:28 +0000190 return false;
191 S = S.substr(1);
192 T = T.substr(1);
193 }
194}
195
196template <class ELFT> bool SectionRule::match(InputSectionBase<ELFT> *S) {
197 return matchStr(SectionPattern, S->getSectionName());
198}
199
Adhemerval Zanellae77b5bf2016-04-06 20:59:11 +0000200class elf::ScriptParser final : public elf::ScriptParserBase {
George Rimarc3794e52016-02-24 09:21:47 +0000201 typedef void (ScriptParser::*Handler)();
202
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000203public:
Rui Ueyama717677a2016-02-11 21:17:59 +0000204 ScriptParser(BumpPtrAllocator *A, StringRef S, bool B)
Adhemerval Zanellae77b5bf2016-04-06 20:59:11 +0000205 : ScriptParserBase(S), Saver(*A), IsUnderSysroot(B) {}
George Rimarf23b2322016-02-19 10:45:45 +0000206
Adhemerval Zanellae77b5bf2016-04-06 20:59:11 +0000207 void run() override;
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000208
209private:
Rui Ueyama52a15092015-10-11 03:28:42 +0000210 void addFile(StringRef Path);
211
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000212 void readAsNeeded();
Denis Protivensky90c50992015-10-08 06:48:38 +0000213 void readEntry();
George Rimar83f406c2015-10-19 17:35:12 +0000214 void readExtern();
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000215 void readGroup();
Rui Ueyama31aa1f82015-10-11 01:31:55 +0000216 void readInclude();
George Rimarc3794e52016-02-24 09:21:47 +0000217 void readNothing() {}
Rui Ueyamaee592822015-10-07 00:25:09 +0000218 void readOutput();
Davide Italiano9159ce92015-10-12 21:50:08 +0000219 void readOutputArch();
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000220 void readOutputFormat();
Davide Italiano68a39a62015-10-08 17:51:41 +0000221 void readSearchDir();
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000222 void readSections();
223
George Rimar652852c2016-04-16 10:10:32 +0000224 void readLocationCounterValue();
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000225 void readOutputSectionDescription();
George Rimar481c2ce2016-02-23 07:47:54 +0000226 void readSectionPatterns(StringRef OutSec, bool Keep);
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000227
Rui Ueyamaa47ee682015-10-11 01:53:04 +0000228 StringSaver Saver;
George Rimarc3794e52016-02-24 09:21:47 +0000229 const static StringMap<Handler> Cmd;
Simon Atanasyan16b0cc92015-11-26 05:53:00 +0000230 bool IsUnderSysroot;
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000231};
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000232
Rafael Espindolae0df00b2016-02-28 00:25:54 +0000233const StringMap<elf::ScriptParser::Handler> elf::ScriptParser::Cmd = {
George Rimarc3794e52016-02-24 09:21:47 +0000234 {"ENTRY", &ScriptParser::readEntry},
235 {"EXTERN", &ScriptParser::readExtern},
236 {"GROUP", &ScriptParser::readGroup},
237 {"INCLUDE", &ScriptParser::readInclude},
238 {"INPUT", &ScriptParser::readGroup},
239 {"OUTPUT", &ScriptParser::readOutput},
240 {"OUTPUT_ARCH", &ScriptParser::readOutputArch},
241 {"OUTPUT_FORMAT", &ScriptParser::readOutputFormat},
242 {"SEARCH_DIR", &ScriptParser::readSearchDir},
243 {"SECTIONS", &ScriptParser::readSections},
244 {";", &ScriptParser::readNothing}};
245
Rui Ueyama717677a2016-02-11 21:17:59 +0000246void ScriptParser::run() {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000247 while (!atEOF()) {
248 StringRef Tok = next();
George Rimarc3794e52016-02-24 09:21:47 +0000249 if (Handler Fn = Cmd.lookup(Tok))
250 (this->*Fn)();
251 else
George Rimar57610422016-03-11 14:43:02 +0000252 setError("unknown directive: " + Tok);
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000253 }
254}
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())
George Rimar777f9632016-03-12 08:31:34 +0000280 setError("unable to find " + S);
Rui Ueyama025d59b2016-02-02 20:27:59 +0000281 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) {
George Rimar57610422016-03-11 14:43:02 +0000336 setError("cannot open " + Tok);
Rui Ueyama025d59b2016-02-02 20:27:59 +0000337 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 != ",") {
George Rimar57610422016-03-11 14:43:02 +0000369 setError("unexpected token: " + Tok);
Rui Ueyama025d59b2016-02-02 20:27:59 +0000370 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("(");
Rafael Espindola06501922016-03-08 17:13:12 +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() {
George Rimar652852c2016-04-16 10:10:32 +0000385 Script->DoLayout = true;
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000386 expect("{");
George Rimar652852c2016-04-16 10:10:32 +0000387 while (!Error && !skip("}")) {
388 StringRef Tok = peek();
389 if (Tok == ".")
390 readLocationCounterValue();
391 else
392 readOutputSectionDescription();
393 }
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000394}
395
George Rimar481c2ce2016-02-23 07:47:54 +0000396void ScriptParser::readSectionPatterns(StringRef OutSec, bool Keep) {
397 expect("(");
398 while (!Error && !skip(")"))
399 Script->Sections.emplace_back(OutSec, next(), Keep);
400}
401
George Rimar652852c2016-04-16 10:10:32 +0000402void ScriptParser::readLocationCounterValue() {
403 expect(".");
404 expect("=");
405 Script->Locations.push_back({Command::Expr, {}, {}});
406 LocationNode &Node = Script->Locations.back();
407 while (!Error) {
408 StringRef Tok = next();
409 if (Tok == ";")
410 break;
411 Node.Expr.push_back(Tok);
412 }
413 if (Node.Expr.empty())
414 error("error in location counter expression");
415}
416
Rui Ueyama717677a2016-02-11 21:17:59 +0000417void ScriptParser::readOutputSectionDescription() {
Rui Ueyama3e808972016-02-28 05:09:11 +0000418 StringRef OutSec = next();
419 Script->SectionOrder.push_back(OutSec);
George Rimar652852c2016-04-16 10:10:32 +0000420 Script->Locations.push_back({Command::Section, {}, {OutSec}});
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000421 expect(":");
422 expect("{");
Rui Ueyama025d59b2016-02-02 20:27:59 +0000423 while (!Error && !skip("}")) {
George Rimar481c2ce2016-02-23 07:47:54 +0000424 StringRef Tok = next();
425 if (Tok == "*") {
Rui Ueyama3e808972016-02-28 05:09:11 +0000426 readSectionPatterns(OutSec, false);
George Rimar481c2ce2016-02-23 07:47:54 +0000427 } else if (Tok == "KEEP") {
428 expect("(");
429 next(); // Skip *
Rui Ueyama3e808972016-02-28 05:09:11 +0000430 readSectionPatterns(OutSec, true);
George Rimar481c2ce2016-02-23 07:47:54 +0000431 expect(")");
432 } else {
George Rimar777f9632016-03-12 08:31:34 +0000433 setError("unknown command " + Tok);
George Rimar481c2ce2016-02-23 07:47:54 +0000434 }
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000435 }
George Rimare2ee72b2016-02-26 14:48:31 +0000436 StringRef Tok = peek();
437 if (Tok.startswith("=")) {
438 if (!Tok.startswith("=0x")) {
Rui Ueyama3ed2f062016-03-13 03:17:44 +0000439 setError("filler should be a hexadecimal value");
George Rimare2ee72b2016-02-26 14:48:31 +0000440 return;
441 }
Rui Ueyama3e808972016-02-28 05:09:11 +0000442 Tok = Tok.substr(3);
443 Script->Filler[OutSec] = parseHex(Tok);
George Rimare2ee72b2016-02-26 14:48:31 +0000444 next();
445 }
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000446}
447
Simon Atanasyan16b0cc92015-11-26 05:53:00 +0000448static bool isUnderSysroot(StringRef Path) {
449 if (Config->Sysroot == "")
450 return false;
451 for (; !Path.empty(); Path = sys::path::parent_path(Path))
452 if (sys::fs::equivalent(Config->Sysroot, Path))
453 return true;
454 return false;
455}
456
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000457// Entry point. The other functions or classes are private to this file.
Rui Ueyamaf9de0d62016-02-11 21:38:55 +0000458void LinkerScript::read(MemoryBufferRef MB) {
Simon Atanasyan16b0cc92015-11-26 05:53:00 +0000459 StringRef Path = MB.getBufferIdentifier();
Rui Ueyamaf9de0d62016-02-11 21:38:55 +0000460 ScriptParser(&Alloc, MB.getBuffer(), isUnderSysroot(Path)).run();
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000461}
Rui Ueyama1ebc8ed2016-02-12 21:47:28 +0000462
463template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF32LE> *);
464template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF32BE> *);
465template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF64LE> *);
466template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF64BE> *);
467
468template bool LinkerScript::isDiscarded(InputSectionBase<ELF32LE> *);
469template bool LinkerScript::isDiscarded(InputSectionBase<ELF32BE> *);
470template bool LinkerScript::isDiscarded(InputSectionBase<ELF64LE> *);
471template bool LinkerScript::isDiscarded(InputSectionBase<ELF64BE> *);
472
George Rimar481c2ce2016-02-23 07:47:54 +0000473template bool LinkerScript::shouldKeep(InputSectionBase<ELF32LE> *);
474template bool LinkerScript::shouldKeep(InputSectionBase<ELF32BE> *);
475template bool LinkerScript::shouldKeep(InputSectionBase<ELF64LE> *);
476template bool LinkerScript::shouldKeep(InputSectionBase<ELF64BE> *);
George Rimar652852c2016-04-16 10:10:32 +0000477
478template void
479LinkerScript::assignAddresses(std::vector<OutputSectionBase<ELF32LE> *> &);
480template void
481LinkerScript::assignAddresses(std::vector<OutputSectionBase<ELF32BE> *> &);
482template void
483LinkerScript::assignAddresses(std::vector<OutputSectionBase<ELF64LE> *> &);
484template void
485LinkerScript::assignAddresses(std::vector<OutputSectionBase<ELF64BE> *> &);