blob: f07dfcde8d9a652afdba5ac87b39714bfdf8744b [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 +000093template <class ELFT>
Rui Ueyama7c18c282016-04-18 21:00:40 +000094static OutputSectionBase<ELFT> *
95findSection(std::vector<OutputSectionBase<ELFT> *> &V, StringRef Name) {
96 for (OutputSectionBase<ELFT> *Sec : V)
97 if (Sec->getName() == Name)
98 return Sec;
99 return nullptr;
100}
101
102template <class ELFT>
103void LinkerScript::assignAddresses(
104 std::vector<OutputSectionBase<ELFT> *> &Sections) {
105 typedef typename ELFT::uint uintX_t;
106
George Rimar652852c2016-04-16 10:10:32 +0000107 // Orphan sections are sections present in the input files which
Rui Ueyama7c18c282016-04-18 21:00:40 +0000108 // are not explicitly placed into the output file by the linker script.
109 // We place orphan sections at end of file.
110 // Other linkers places them using some heuristics as described in
George Rimar652852c2016-04-16 10:10:32 +0000111 // https://sourceware.org/binutils/docs/ld/Orphan-Sections.html#Orphan-Sections.
Rui Ueyama7c18c282016-04-18 21:00:40 +0000112 for (OutputSectionBase<ELFT> *Sec : Sections) {
George Rimar652852c2016-04-16 10:10:32 +0000113 StringRef Name = Sec->getName();
114 auto I = std::find(SectionOrder.begin(), SectionOrder.end(), Name);
115 if (I == SectionOrder.end())
Rui Ueyama9e957a02016-04-18 21:00:45 +0000116 Commands.push_back({SectionKind, {}, Name});
George Rimar652852c2016-04-16 10:10:32 +0000117 }
George Rimar652852c2016-04-16 10:10:32 +0000118
Rui Ueyama7c18c282016-04-18 21:00:40 +0000119 // Assign addresses as instructed by linker script SECTIONS sub-commands.
George Rimar652852c2016-04-16 10:10:32 +0000120 uintX_t ThreadBssOffset = 0;
121 uintX_t VA =
122 Out<ELFT>::ElfHeader->getSize() + Out<ELFT>::ProgramHeaders->getSize();
123
Rui Ueyama9e957a02016-04-18 21:00:45 +0000124 for (SectionsCommand &Cmd : Commands) {
125 if (Cmd.Kind == ExprKind) {
126 VA = evaluate(Cmd.Expr, VA);
George Rimar652852c2016-04-16 10:10:32 +0000127 continue;
128 }
129
Rui Ueyama9e957a02016-04-18 21:00:45 +0000130 OutputSectionBase<ELFT> *Sec = findSection(Sections, Cmd.SectionName);
Rui Ueyama7c18c282016-04-18 21:00:40 +0000131 if (!Sec)
George Rimar652852c2016-04-16 10:10:32 +0000132 continue;
133
George Rimar652852c2016-04-16 10:10:32 +0000134 if ((Sec->getFlags() & SHF_TLS) && Sec->getType() == SHT_NOBITS) {
135 uintX_t TVA = VA + ThreadBssOffset;
Rui Ueyama7c18c282016-04-18 21:00:40 +0000136 TVA = alignTo(TVA, Sec->getAlign());
George Rimar652852c2016-04-16 10:10:32 +0000137 Sec->setVA(TVA);
138 ThreadBssOffset = TVA - VA + Sec->getSize();
139 continue;
140 }
141
142 if (Sec->getFlags() & SHF_ALLOC) {
Rui Ueyama7c18c282016-04-18 21:00:40 +0000143 VA = alignTo(VA, Sec->getAlign());
George Rimar652852c2016-04-16 10:10:32 +0000144 Sec->setVA(VA);
145 VA += Sec->getSize();
146 continue;
147 }
148 }
149}
150
George Rimare2ee72b2016-02-26 14:48:31 +0000151ArrayRef<uint8_t> LinkerScript::getFiller(StringRef Name) {
Rui Ueyama3e808972016-02-28 05:09:11 +0000152 auto I = Filler.find(Name);
153 if (I == Filler.end())
154 return {};
155 return I->second;
George Rimare2ee72b2016-02-26 14:48:31 +0000156}
157
Rui Ueyamae9c58062016-02-12 20:41:43 +0000158// A compartor to sort output sections. Returns -1 or 1 if both
159// A and B are mentioned in linker scripts. Otherwise, returns 0
160// to use the default rule which is implemented in Writer.cpp.
Rui Ueyama717677a2016-02-11 21:17:59 +0000161int LinkerScript::compareSections(StringRef A, StringRef B) {
Rui Ueyama3e808972016-02-28 05:09:11 +0000162 auto E = SectionOrder.end();
163 auto I = std::find(SectionOrder.begin(), E, A);
164 auto J = std::find(SectionOrder.begin(), E, B);
165 if (I == E || J == E)
Rui Ueyama717677a2016-02-11 21:17:59 +0000166 return 0;
167 return I < J ? -1 : 1;
168}
169
George Rimarcb2aeb62016-02-24 08:49:50 +0000170// Returns true if S matches T. S can contain glob meta-characters.
171// The asterisk ('*') matches zero or more characacters, and the question
172// mark ('?') matches one character.
Rui Ueyama1ebc8ed2016-02-12 21:47:28 +0000173static bool matchStr(StringRef S, StringRef T) {
174 for (;;) {
175 if (S.empty())
176 return T.empty();
177 if (S[0] == '*') {
178 S = S.substr(1);
179 if (S.empty())
180 // Fast path. If a pattern is '*', it matches anything.
181 return true;
182 for (size_t I = 0, E = T.size(); I < E; ++I)
183 if (matchStr(S, T.substr(I)))
184 return true;
185 return false;
186 }
George Rimarcb2aeb62016-02-24 08:49:50 +0000187 if (T.empty() || (S[0] != T[0] && S[0] != '?'))
Rui Ueyama1ebc8ed2016-02-12 21:47:28 +0000188 return false;
189 S = S.substr(1);
190 T = T.substr(1);
191 }
192}
193
194template <class ELFT> bool SectionRule::match(InputSectionBase<ELFT> *S) {
195 return matchStr(SectionPattern, S->getSectionName());
196}
197
Adhemerval Zanellae77b5bf2016-04-06 20:59:11 +0000198class elf::ScriptParser final : public elf::ScriptParserBase {
George Rimarc3794e52016-02-24 09:21:47 +0000199 typedef void (ScriptParser::*Handler)();
200
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000201public:
Rui Ueyama717677a2016-02-11 21:17:59 +0000202 ScriptParser(BumpPtrAllocator *A, StringRef S, bool B)
Adhemerval Zanellae77b5bf2016-04-06 20:59:11 +0000203 : ScriptParserBase(S), Saver(*A), IsUnderSysroot(B) {}
George Rimarf23b2322016-02-19 10:45:45 +0000204
Adhemerval Zanellae77b5bf2016-04-06 20:59:11 +0000205 void run() override;
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000206
207private:
Rui Ueyama52a15092015-10-11 03:28:42 +0000208 void addFile(StringRef Path);
209
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000210 void readAsNeeded();
Denis Protivensky90c50992015-10-08 06:48:38 +0000211 void readEntry();
George Rimar83f406c2015-10-19 17:35:12 +0000212 void readExtern();
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000213 void readGroup();
Rui Ueyama31aa1f82015-10-11 01:31:55 +0000214 void readInclude();
George Rimarc3794e52016-02-24 09:21:47 +0000215 void readNothing() {}
Rui Ueyamaee592822015-10-07 00:25:09 +0000216 void readOutput();
Davide Italiano9159ce92015-10-12 21:50:08 +0000217 void readOutputArch();
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000218 void readOutputFormat();
Davide Italiano68a39a62015-10-08 17:51:41 +0000219 void readSearchDir();
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000220 void readSections();
221
George Rimar652852c2016-04-16 10:10:32 +0000222 void readLocationCounterValue();
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000223 void readOutputSectionDescription();
George Rimar481c2ce2016-02-23 07:47:54 +0000224 void readSectionPatterns(StringRef OutSec, bool Keep);
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000225
Rui Ueyamaa47ee682015-10-11 01:53:04 +0000226 StringSaver Saver;
George Rimarc3794e52016-02-24 09:21:47 +0000227 const static StringMap<Handler> Cmd;
Simon Atanasyan16b0cc92015-11-26 05:53:00 +0000228 bool IsUnderSysroot;
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000229};
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000230
Rafael Espindolae0df00b2016-02-28 00:25:54 +0000231const StringMap<elf::ScriptParser::Handler> elf::ScriptParser::Cmd = {
George Rimarc3794e52016-02-24 09:21:47 +0000232 {"ENTRY", &ScriptParser::readEntry},
233 {"EXTERN", &ScriptParser::readExtern},
234 {"GROUP", &ScriptParser::readGroup},
235 {"INCLUDE", &ScriptParser::readInclude},
236 {"INPUT", &ScriptParser::readGroup},
237 {"OUTPUT", &ScriptParser::readOutput},
238 {"OUTPUT_ARCH", &ScriptParser::readOutputArch},
239 {"OUTPUT_FORMAT", &ScriptParser::readOutputFormat},
240 {"SEARCH_DIR", &ScriptParser::readSearchDir},
241 {"SECTIONS", &ScriptParser::readSections},
242 {";", &ScriptParser::readNothing}};
243
Rui Ueyama717677a2016-02-11 21:17:59 +0000244void ScriptParser::run() {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000245 while (!atEOF()) {
246 StringRef Tok = next();
George Rimarc3794e52016-02-24 09:21:47 +0000247 if (Handler Fn = Cmd.lookup(Tok))
248 (this->*Fn)();
249 else
George Rimar57610422016-03-11 14:43:02 +0000250 setError("unknown directive: " + Tok);
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000251 }
252}
253
Rui Ueyama717677a2016-02-11 21:17:59 +0000254void ScriptParser::addFile(StringRef S) {
Simon Atanasyan16b0cc92015-11-26 05:53:00 +0000255 if (IsUnderSysroot && S.startswith("/")) {
256 SmallString<128> Path;
257 (Config->Sysroot + S).toStringRef(Path);
258 if (sys::fs::exists(Path)) {
259 Driver->addFile(Saver.save(Path.str()));
260 return;
261 }
262 }
263
Rui Ueyamaf03f3cc2015-10-13 00:09:21 +0000264 if (sys::path::is_absolute(S)) {
Rui Ueyama52a15092015-10-11 03:28:42 +0000265 Driver->addFile(S);
266 } else if (S.startswith("=")) {
267 if (Config->Sysroot.empty())
268 Driver->addFile(S.substr(1));
269 else
270 Driver->addFile(Saver.save(Config->Sysroot + "/" + S.substr(1)));
271 } else if (S.startswith("-l")) {
Rui Ueyama21eecb42016-02-02 21:13:09 +0000272 Driver->addLibrary(S.substr(2));
Simon Atanasyana1b8fc32015-11-26 20:23:46 +0000273 } else if (sys::fs::exists(S)) {
274 Driver->addFile(S);
Rui Ueyama52a15092015-10-11 03:28:42 +0000275 } else {
276 std::string Path = findFromSearchPaths(S);
277 if (Path.empty())
George Rimar777f9632016-03-12 08:31:34 +0000278 setError("unable to find " + S);
Rui Ueyama025d59b2016-02-02 20:27:59 +0000279 else
280 Driver->addFile(Saver.save(Path));
Rui Ueyama52a15092015-10-11 03:28:42 +0000281 }
282}
283
Rui Ueyama717677a2016-02-11 21:17:59 +0000284void ScriptParser::readAsNeeded() {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000285 expect("(");
Rui Ueyama35da9b62015-10-11 20:59:12 +0000286 bool Orig = Config->AsNeeded;
287 Config->AsNeeded = true;
Rui Ueyama025d59b2016-02-02 20:27:59 +0000288 while (!Error) {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000289 StringRef Tok = next();
290 if (Tok == ")")
Rui Ueyama35da9b62015-10-11 20:59:12 +0000291 break;
Rui Ueyama52a15092015-10-11 03:28:42 +0000292 addFile(Tok);
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000293 }
Rui Ueyama35da9b62015-10-11 20:59:12 +0000294 Config->AsNeeded = Orig;
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000295}
296
Rui Ueyama717677a2016-02-11 21:17:59 +0000297void ScriptParser::readEntry() {
Denis Protivensky90c50992015-10-08 06:48:38 +0000298 // -e <symbol> takes predecence over ENTRY(<symbol>).
299 expect("(");
300 StringRef Tok = next();
301 if (Config->Entry.empty())
302 Config->Entry = Tok;
303 expect(")");
304}
305
Rui Ueyama717677a2016-02-11 21:17:59 +0000306void ScriptParser::readExtern() {
George Rimar83f406c2015-10-19 17:35:12 +0000307 expect("(");
Rui Ueyama025d59b2016-02-02 20:27:59 +0000308 while (!Error) {
George Rimar83f406c2015-10-19 17:35:12 +0000309 StringRef Tok = next();
310 if (Tok == ")")
311 return;
312 Config->Undefined.push_back(Tok);
313 }
314}
315
Rui Ueyama717677a2016-02-11 21:17:59 +0000316void ScriptParser::readGroup() {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000317 expect("(");
Rui Ueyama025d59b2016-02-02 20:27:59 +0000318 while (!Error) {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000319 StringRef Tok = next();
320 if (Tok == ")")
321 return;
322 if (Tok == "AS_NEEDED") {
323 readAsNeeded();
324 continue;
325 }
Rui Ueyama52a15092015-10-11 03:28:42 +0000326 addFile(Tok);
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000327 }
328}
329
Rui Ueyama717677a2016-02-11 21:17:59 +0000330void ScriptParser::readInclude() {
Rui Ueyama31aa1f82015-10-11 01:31:55 +0000331 StringRef Tok = next();
332 auto MBOrErr = MemoryBuffer::getFile(Tok);
Rui Ueyama025d59b2016-02-02 20:27:59 +0000333 if (!MBOrErr) {
George Rimar57610422016-03-11 14:43:02 +0000334 setError("cannot open " + Tok);
Rui Ueyama025d59b2016-02-02 20:27:59 +0000335 return;
336 }
Rui Ueyama31aa1f82015-10-11 01:31:55 +0000337 std::unique_ptr<MemoryBuffer> &MB = *MBOrErr;
Rui Ueyamaa47ee682015-10-11 01:53:04 +0000338 StringRef S = Saver.save(MB->getMemBufferRef().getBuffer());
339 std::vector<StringRef> V = tokenize(S);
Rui Ueyama31aa1f82015-10-11 01:31:55 +0000340 Tokens.insert(Tokens.begin() + Pos, V.begin(), V.end());
Rui Ueyama31aa1f82015-10-11 01:31:55 +0000341}
342
Rui Ueyama717677a2016-02-11 21:17:59 +0000343void ScriptParser::readOutput() {
Rui Ueyamaee592822015-10-07 00:25:09 +0000344 // -o <file> takes predecence over OUTPUT(<file>).
345 expect("(");
346 StringRef Tok = next();
347 if (Config->OutputFile.empty())
348 Config->OutputFile = Tok;
349 expect(")");
350}
351
Rui Ueyama717677a2016-02-11 21:17:59 +0000352void ScriptParser::readOutputArch() {
Davide Italiano9159ce92015-10-12 21:50:08 +0000353 // Error checking only for now.
354 expect("(");
355 next();
356 expect(")");
357}
358
Rui Ueyama717677a2016-02-11 21:17:59 +0000359void ScriptParser::readOutputFormat() {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000360 // Error checking only for now.
361 expect("(");
362 next();
Davide Italiano6836c612015-10-12 21:08:41 +0000363 StringRef Tok = next();
364 if (Tok == ")")
365 return;
Rui Ueyama025d59b2016-02-02 20:27:59 +0000366 if (Tok != ",") {
George Rimar57610422016-03-11 14:43:02 +0000367 setError("unexpected token: " + Tok);
Rui Ueyama025d59b2016-02-02 20:27:59 +0000368 return;
369 }
Davide Italiano6836c612015-10-12 21:08:41 +0000370 next();
371 expect(",");
372 next();
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000373 expect(")");
374}
375
Rui Ueyama717677a2016-02-11 21:17:59 +0000376void ScriptParser::readSearchDir() {
Davide Italiano68a39a62015-10-08 17:51:41 +0000377 expect("(");
Rafael Espindola06501922016-03-08 17:13:12 +0000378 Config->SearchPaths.push_back(next());
Davide Italiano68a39a62015-10-08 17:51:41 +0000379 expect(")");
380}
381
Rui Ueyama717677a2016-02-11 21:17:59 +0000382void ScriptParser::readSections() {
George Rimar652852c2016-04-16 10:10:32 +0000383 Script->DoLayout = true;
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000384 expect("{");
George Rimar652852c2016-04-16 10:10:32 +0000385 while (!Error && !skip("}")) {
386 StringRef Tok = peek();
387 if (Tok == ".")
388 readLocationCounterValue();
389 else
390 readOutputSectionDescription();
391 }
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000392}
393
George Rimar481c2ce2016-02-23 07:47:54 +0000394void ScriptParser::readSectionPatterns(StringRef OutSec, bool Keep) {
395 expect("(");
396 while (!Error && !skip(")"))
397 Script->Sections.emplace_back(OutSec, next(), Keep);
398}
399
George Rimar652852c2016-04-16 10:10:32 +0000400void ScriptParser::readLocationCounterValue() {
401 expect(".");
402 expect("=");
Rui Ueyama9e957a02016-04-18 21:00:45 +0000403 Script->Commands.push_back({ExprKind, {}, ""});
404 SectionsCommand &Cmd = Script->Commands.back();
George Rimar652852c2016-04-16 10:10:32 +0000405 while (!Error) {
406 StringRef Tok = next();
407 if (Tok == ";")
408 break;
Rui Ueyama9e957a02016-04-18 21:00:45 +0000409 Cmd.Expr.push_back(Tok);
George Rimar652852c2016-04-16 10:10:32 +0000410 }
Rui Ueyama9e957a02016-04-18 21:00:45 +0000411 if (Cmd.Expr.empty())
George Rimar652852c2016-04-16 10:10:32 +0000412 error("error in location counter expression");
413}
414
Rui Ueyama717677a2016-02-11 21:17:59 +0000415void ScriptParser::readOutputSectionDescription() {
Rui Ueyama3e808972016-02-28 05:09:11 +0000416 StringRef OutSec = next();
417 Script->SectionOrder.push_back(OutSec);
Rui Ueyama9e957a02016-04-18 21:00:45 +0000418 Script->Commands.push_back({SectionKind, {}, OutSec});
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000419 expect(":");
420 expect("{");
Rui Ueyama025d59b2016-02-02 20:27:59 +0000421 while (!Error && !skip("}")) {
George Rimar481c2ce2016-02-23 07:47:54 +0000422 StringRef Tok = next();
423 if (Tok == "*") {
Rui Ueyama3e808972016-02-28 05:09:11 +0000424 readSectionPatterns(OutSec, false);
George Rimar481c2ce2016-02-23 07:47:54 +0000425 } else if (Tok == "KEEP") {
426 expect("(");
427 next(); // Skip *
Rui Ueyama3e808972016-02-28 05:09:11 +0000428 readSectionPatterns(OutSec, true);
George Rimar481c2ce2016-02-23 07:47:54 +0000429 expect(")");
430 } else {
George Rimar777f9632016-03-12 08:31:34 +0000431 setError("unknown command " + Tok);
George Rimar481c2ce2016-02-23 07:47:54 +0000432 }
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000433 }
George Rimare2ee72b2016-02-26 14:48:31 +0000434 StringRef Tok = peek();
435 if (Tok.startswith("=")) {
436 if (!Tok.startswith("=0x")) {
Rui Ueyama3ed2f062016-03-13 03:17:44 +0000437 setError("filler should be a hexadecimal value");
George Rimare2ee72b2016-02-26 14:48:31 +0000438 return;
439 }
Rui Ueyama3e808972016-02-28 05:09:11 +0000440 Tok = Tok.substr(3);
441 Script->Filler[OutSec] = parseHex(Tok);
George Rimare2ee72b2016-02-26 14:48:31 +0000442 next();
443 }
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000444}
445
Simon Atanasyan16b0cc92015-11-26 05:53:00 +0000446static bool isUnderSysroot(StringRef Path) {
447 if (Config->Sysroot == "")
448 return false;
449 for (; !Path.empty(); Path = sys::path::parent_path(Path))
450 if (sys::fs::equivalent(Config->Sysroot, Path))
451 return true;
452 return false;
453}
454
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000455// Entry point. The other functions or classes are private to this file.
Rui Ueyamaf9de0d62016-02-11 21:38:55 +0000456void LinkerScript::read(MemoryBufferRef MB) {
Simon Atanasyan16b0cc92015-11-26 05:53:00 +0000457 StringRef Path = MB.getBufferIdentifier();
Rui Ueyamaf9de0d62016-02-11 21:38:55 +0000458 ScriptParser(&Alloc, MB.getBuffer(), isUnderSysroot(Path)).run();
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000459}
Rui Ueyama1ebc8ed2016-02-12 21:47:28 +0000460
461template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF32LE> *);
462template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF32BE> *);
463template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF64LE> *);
464template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF64BE> *);
465
466template bool LinkerScript::isDiscarded(InputSectionBase<ELF32LE> *);
467template bool LinkerScript::isDiscarded(InputSectionBase<ELF32BE> *);
468template bool LinkerScript::isDiscarded(InputSectionBase<ELF64LE> *);
469template bool LinkerScript::isDiscarded(InputSectionBase<ELF64BE> *);
470
George Rimar481c2ce2016-02-23 07:47:54 +0000471template bool LinkerScript::shouldKeep(InputSectionBase<ELF32LE> *);
472template bool LinkerScript::shouldKeep(InputSectionBase<ELF32BE> *);
473template bool LinkerScript::shouldKeep(InputSectionBase<ELF64LE> *);
474template bool LinkerScript::shouldKeep(InputSectionBase<ELF64BE> *);
George Rimar652852c2016-04-16 10:10:32 +0000475
476template void
477LinkerScript::assignAddresses(std::vector<OutputSectionBase<ELF32LE> *> &);
478template void
479LinkerScript::assignAddresses(std::vector<OutputSectionBase<ELF32BE> *> &);
480template void
481LinkerScript::assignAddresses(std::vector<OutputSectionBase<ELF64LE> *> &);
482template void
483LinkerScript::assignAddresses(std::vector<OutputSectionBase<ELF64BE> *> &);