blob: 536109fa625d2ea8a54b0be4ecc8d96dff6be638 [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"
19#include "SymbolTable.h"
20#include "llvm/Support/FileSystem.h"
21#include "llvm/Support/MemoryBuffer.h"
Rui Ueyamaf03f3cc2015-10-13 00:09:21 +000022#include "llvm/Support/Path.h"
Rui Ueyamaa47ee682015-10-11 01:53:04 +000023#include "llvm/Support/StringSaver.h"
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +000024
25using namespace llvm;
26using namespace lld;
27using namespace lld::elf2;
28
Rui Ueyama717677a2016-02-11 21:17:59 +000029LinkerScript *elf2::Script;
30
31void LinkerScript::finalize() {
32 for (const std::pair<StringRef, std::vector<StringRef>> &P : Sections)
33 for (StringRef S : P.second)
34 RevSections[S] = P.first;
35}
36
37StringRef LinkerScript::getOutputSection(StringRef S) {
38 return RevSections.lookup(S);
39}
40
41bool LinkerScript::isDiscarded(StringRef S) {
42 return RevSections.lookup(S) == "/DISCARD/";
43}
44
45int LinkerScript::compareSections(StringRef A, StringRef B) {
46 auto I = Sections.find(A);
47 auto E = Sections.end();
48 if (I == E)
49 return 0;
50 auto J = Sections.find(B);
51 if (J == E)
52 return 0;
53 return I < J ? -1 : 1;
54}
55
56class elf2::ScriptParser {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +000057public:
Rui Ueyama717677a2016-02-11 21:17:59 +000058 ScriptParser(BumpPtrAllocator *A, StringRef S, bool B)
Simon Atanasyan16b0cc92015-11-26 05:53:00 +000059 : Saver(*A), Tokens(tokenize(S)), IsUnderSysroot(B) {}
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +000060 void run();
61
62private:
Rui Ueyama025d59b2016-02-02 20:27:59 +000063 void setError(const Twine &Msg);
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +000064 static std::vector<StringRef> tokenize(StringRef S);
65 static StringRef skipSpace(StringRef S);
Rui Ueyama025d59b2016-02-02 20:27:59 +000066 bool atEOF();
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +000067 StringRef next();
Denis Protivensky8e3b38a2015-11-12 09:52:08 +000068 bool skip(StringRef Tok);
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +000069 void expect(StringRef Expect);
70
Rui Ueyama52a15092015-10-11 03:28:42 +000071 void addFile(StringRef Path);
72
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +000073 void readAsNeeded();
Denis Protivensky90c50992015-10-08 06:48:38 +000074 void readEntry();
George Rimar83f406c2015-10-19 17:35:12 +000075 void readExtern();
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +000076 void readGroup();
Rui Ueyama31aa1f82015-10-11 01:31:55 +000077 void readInclude();
Rui Ueyamaee592822015-10-07 00:25:09 +000078 void readOutput();
Davide Italiano9159ce92015-10-12 21:50:08 +000079 void readOutputArch();
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +000080 void readOutputFormat();
Davide Italiano68a39a62015-10-08 17:51:41 +000081 void readSearchDir();
Denis Protivensky8e3b38a2015-11-12 09:52:08 +000082 void readSections();
83
84 void readOutputSectionDescription();
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +000085
Rui Ueyamaa47ee682015-10-11 01:53:04 +000086 StringSaver Saver;
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +000087 std::vector<StringRef> Tokens;
Rui Ueyama025d59b2016-02-02 20:27:59 +000088 bool Error = false;
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +000089 size_t Pos = 0;
Simon Atanasyan16b0cc92015-11-26 05:53:00 +000090 bool IsUnderSysroot;
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +000091};
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +000092
Rui Ueyama717677a2016-02-11 21:17:59 +000093void ScriptParser::run() {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +000094 while (!atEOF()) {
95 StringRef Tok = next();
Davide Italiano10d268d2015-10-13 20:48:56 +000096 if (Tok == ";")
97 continue;
Denis Protivensky90c50992015-10-08 06:48:38 +000098 if (Tok == "ENTRY") {
99 readEntry();
George Rimar83f406c2015-10-19 17:35:12 +0000100 } else if (Tok == "EXTERN") {
101 readExtern();
Rui Ueyama00f97272015-10-11 01:31:57 +0000102 } else if (Tok == "GROUP" || Tok == "INPUT") {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000103 readGroup();
Rui Ueyama31aa1f82015-10-11 01:31:55 +0000104 } else if (Tok == "INCLUDE") {
105 readInclude();
Rui Ueyamaee592822015-10-07 00:25:09 +0000106 } else if (Tok == "OUTPUT") {
107 readOutput();
Davide Italiano9159ce92015-10-12 21:50:08 +0000108 } else if (Tok == "OUTPUT_ARCH") {
109 readOutputArch();
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000110 } else if (Tok == "OUTPUT_FORMAT") {
111 readOutputFormat();
Davide Italiano68a39a62015-10-08 17:51:41 +0000112 } else if (Tok == "SEARCH_DIR") {
113 readSearchDir();
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000114 } else if (Tok == "SECTIONS") {
115 readSections();
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000116 } else {
Rui Ueyama025d59b2016-02-02 20:27:59 +0000117 setError("unknown directive: " + Tok);
118 return;
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000119 }
120 }
121}
122
Rui Ueyama025d59b2016-02-02 20:27:59 +0000123// We don't want to record cascading errors. Keep only the first one.
Rui Ueyama717677a2016-02-11 21:17:59 +0000124void ScriptParser::setError(const Twine &Msg) {
Rui Ueyama025d59b2016-02-02 20:27:59 +0000125 if (Error)
126 return;
127 error(Msg);
128 Error = true;
129}
130
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000131// Split S into linker script tokens.
Rui Ueyama717677a2016-02-11 21:17:59 +0000132std::vector<StringRef> ScriptParser::tokenize(StringRef S) {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000133 std::vector<StringRef> Ret;
134 for (;;) {
135 S = skipSpace(S);
136 if (S.empty())
137 return Ret;
138
139 // Quoted token
140 if (S.startswith("\"")) {
141 size_t E = S.find("\"", 1);
Rui Ueyama025d59b2016-02-02 20:27:59 +0000142 if (E == StringRef::npos) {
143 error("unclosed quote");
144 return {};
145 }
Pete Cooper60259332016-01-22 23:46:37 +0000146 Ret.push_back(S.substr(1, E - 1));
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000147 S = S.substr(E + 1);
148 continue;
149 }
150
151 // Unquoted token
152 size_t Pos = S.find_first_not_of(
153 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
154 "0123456789_.$/\\~=+[]*?-:");
155 // A character that cannot start a word (which is usually a
156 // punctuation) forms a single character token.
157 if (Pos == 0)
158 Pos = 1;
159 Ret.push_back(S.substr(0, Pos));
160 S = S.substr(Pos);
161 }
162}
163
164// Skip leading whitespace characters or /**/-style comments.
Rui Ueyama717677a2016-02-11 21:17:59 +0000165StringRef ScriptParser::skipSpace(StringRef S) {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000166 for (;;) {
167 if (S.startswith("/*")) {
168 size_t E = S.find("*/", 2);
Rui Ueyama025d59b2016-02-02 20:27:59 +0000169 if (E == StringRef::npos) {
170 error("unclosed comment in a linker script");
171 return "";
172 }
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000173 S = S.substr(E + 2);
174 continue;
175 }
176 size_t Size = S.size();
177 S = S.ltrim();
178 if (S.size() == Size)
179 return S;
180 }
181}
182
Rui Ueyama025d59b2016-02-02 20:27:59 +0000183// An errneous token is handled as if it were the last token before EOF.
Rui Ueyama717677a2016-02-11 21:17:59 +0000184bool ScriptParser::atEOF() { return Error || Tokens.size() == Pos; }
Rui Ueyama025d59b2016-02-02 20:27:59 +0000185
Rui Ueyama717677a2016-02-11 21:17:59 +0000186StringRef ScriptParser::next() {
Rui Ueyama025d59b2016-02-02 20:27:59 +0000187 if (Error)
188 return "";
189 if (atEOF()) {
190 setError("unexpected EOF");
191 return "";
192 }
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000193 return Tokens[Pos++];
194}
195
Rui Ueyama717677a2016-02-11 21:17:59 +0000196bool ScriptParser::skip(StringRef Tok) {
Rui Ueyama025d59b2016-02-02 20:27:59 +0000197 if (Error)
198 return false;
199 if (atEOF()) {
200 setError("unexpected EOF");
201 return false;
202 }
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000203 if (Tok != Tokens[Pos])
204 return false;
205 ++Pos;
206 return true;
207}
208
Rui Ueyama717677a2016-02-11 21:17:59 +0000209void ScriptParser::expect(StringRef Expect) {
Rui Ueyama025d59b2016-02-02 20:27:59 +0000210 if (Error)
211 return;
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000212 StringRef Tok = next();
213 if (Tok != Expect)
Rui Ueyama025d59b2016-02-02 20:27:59 +0000214 setError(Expect + " expected, but got " + Tok);
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000215}
216
Rui Ueyama717677a2016-02-11 21:17:59 +0000217void ScriptParser::addFile(StringRef S) {
Simon Atanasyan16b0cc92015-11-26 05:53:00 +0000218 if (IsUnderSysroot && S.startswith("/")) {
219 SmallString<128> Path;
220 (Config->Sysroot + S).toStringRef(Path);
221 if (sys::fs::exists(Path)) {
222 Driver->addFile(Saver.save(Path.str()));
223 return;
224 }
225 }
226
Rui Ueyamaf03f3cc2015-10-13 00:09:21 +0000227 if (sys::path::is_absolute(S)) {
Rui Ueyama52a15092015-10-11 03:28:42 +0000228 Driver->addFile(S);
229 } else if (S.startswith("=")) {
230 if (Config->Sysroot.empty())
231 Driver->addFile(S.substr(1));
232 else
233 Driver->addFile(Saver.save(Config->Sysroot + "/" + S.substr(1)));
234 } else if (S.startswith("-l")) {
Rui Ueyama21eecb42016-02-02 21:13:09 +0000235 Driver->addLibrary(S.substr(2));
Simon Atanasyana1b8fc32015-11-26 20:23:46 +0000236 } else if (sys::fs::exists(S)) {
237 Driver->addFile(S);
Rui Ueyama52a15092015-10-11 03:28:42 +0000238 } else {
239 std::string Path = findFromSearchPaths(S);
240 if (Path.empty())
Rui Ueyama025d59b2016-02-02 20:27:59 +0000241 setError("Unable to find " + S);
242 else
243 Driver->addFile(Saver.save(Path));
Rui Ueyama52a15092015-10-11 03:28:42 +0000244 }
245}
246
Rui Ueyama717677a2016-02-11 21:17:59 +0000247void ScriptParser::readAsNeeded() {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000248 expect("(");
Rui Ueyama35da9b62015-10-11 20:59:12 +0000249 bool Orig = Config->AsNeeded;
250 Config->AsNeeded = true;
Rui Ueyama025d59b2016-02-02 20:27:59 +0000251 while (!Error) {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000252 StringRef Tok = next();
253 if (Tok == ")")
Rui Ueyama35da9b62015-10-11 20:59:12 +0000254 break;
Rui Ueyama52a15092015-10-11 03:28:42 +0000255 addFile(Tok);
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000256 }
Rui Ueyama35da9b62015-10-11 20:59:12 +0000257 Config->AsNeeded = Orig;
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000258}
259
Rui Ueyama717677a2016-02-11 21:17:59 +0000260void ScriptParser::readEntry() {
Denis Protivensky90c50992015-10-08 06:48:38 +0000261 // -e <symbol> takes predecence over ENTRY(<symbol>).
262 expect("(");
263 StringRef Tok = next();
264 if (Config->Entry.empty())
265 Config->Entry = Tok;
266 expect(")");
267}
268
Rui Ueyama717677a2016-02-11 21:17:59 +0000269void ScriptParser::readExtern() {
George Rimar83f406c2015-10-19 17:35:12 +0000270 expect("(");
Rui Ueyama025d59b2016-02-02 20:27:59 +0000271 while (!Error) {
George Rimar83f406c2015-10-19 17:35:12 +0000272 StringRef Tok = next();
273 if (Tok == ")")
274 return;
275 Config->Undefined.push_back(Tok);
276 }
277}
278
Rui Ueyama717677a2016-02-11 21:17:59 +0000279void ScriptParser::readGroup() {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000280 expect("(");
Rui Ueyama025d59b2016-02-02 20:27:59 +0000281 while (!Error) {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000282 StringRef Tok = next();
283 if (Tok == ")")
284 return;
285 if (Tok == "AS_NEEDED") {
286 readAsNeeded();
287 continue;
288 }
Rui Ueyama52a15092015-10-11 03:28:42 +0000289 addFile(Tok);
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000290 }
291}
292
Rui Ueyama717677a2016-02-11 21:17:59 +0000293void ScriptParser::readInclude() {
Rui Ueyama31aa1f82015-10-11 01:31:55 +0000294 StringRef Tok = next();
295 auto MBOrErr = MemoryBuffer::getFile(Tok);
Rui Ueyama025d59b2016-02-02 20:27:59 +0000296 if (!MBOrErr) {
297 setError("cannot open " + Tok);
298 return;
299 }
Rui Ueyama31aa1f82015-10-11 01:31:55 +0000300 std::unique_ptr<MemoryBuffer> &MB = *MBOrErr;
Rui Ueyamaa47ee682015-10-11 01:53:04 +0000301 StringRef S = Saver.save(MB->getMemBufferRef().getBuffer());
302 std::vector<StringRef> V = tokenize(S);
Rui Ueyama31aa1f82015-10-11 01:31:55 +0000303 Tokens.insert(Tokens.begin() + Pos, V.begin(), V.end());
Rui Ueyama31aa1f82015-10-11 01:31:55 +0000304}
305
Rui Ueyama717677a2016-02-11 21:17:59 +0000306void ScriptParser::readOutput() {
Rui Ueyamaee592822015-10-07 00:25:09 +0000307 // -o <file> takes predecence over OUTPUT(<file>).
308 expect("(");
309 StringRef Tok = next();
310 if (Config->OutputFile.empty())
311 Config->OutputFile = Tok;
312 expect(")");
313}
314
Rui Ueyama717677a2016-02-11 21:17:59 +0000315void ScriptParser::readOutputArch() {
Davide Italiano9159ce92015-10-12 21:50:08 +0000316 // Error checking only for now.
317 expect("(");
318 next();
319 expect(")");
320}
321
Rui Ueyama717677a2016-02-11 21:17:59 +0000322void ScriptParser::readOutputFormat() {
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000323 // Error checking only for now.
324 expect("(");
325 next();
Davide Italiano6836c612015-10-12 21:08:41 +0000326 StringRef Tok = next();
327 if (Tok == ")")
328 return;
Rui Ueyama025d59b2016-02-02 20:27:59 +0000329 if (Tok != ",") {
330 setError("unexpected token: " + Tok);
331 return;
332 }
Davide Italiano6836c612015-10-12 21:08:41 +0000333 next();
334 expect(",");
335 next();
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000336 expect(")");
337}
338
Rui Ueyama717677a2016-02-11 21:17:59 +0000339void ScriptParser::readSearchDir() {
Davide Italiano68a39a62015-10-08 17:51:41 +0000340 expect("(");
Rui Ueyama52a15092015-10-11 03:28:42 +0000341 Config->SearchPaths.push_back(next());
Davide Italiano68a39a62015-10-08 17:51:41 +0000342 expect(")");
343}
344
Rui Ueyama717677a2016-02-11 21:17:59 +0000345void ScriptParser::readSections() {
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000346 expect("{");
Rui Ueyama025d59b2016-02-02 20:27:59 +0000347 while (!Error && !skip("}"))
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000348 readOutputSectionDescription();
349}
350
Rui Ueyama717677a2016-02-11 21:17:59 +0000351void ScriptParser::readOutputSectionDescription() {
352 std::vector<StringRef> &V = Script->Sections[next()];
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000353 expect(":");
354 expect("{");
Rui Ueyama025d59b2016-02-02 20:27:59 +0000355 while (!Error && !skip("}")) {
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000356 next(); // Skip input file name.
357 expect("(");
Rui Ueyama025d59b2016-02-02 20:27:59 +0000358 while (!Error && !skip(")"))
Rui Ueyama717677a2016-02-11 21:17:59 +0000359 V.push_back(next());
Denis Protivensky8e3b38a2015-11-12 09:52:08 +0000360 }
361}
362
Simon Atanasyan16b0cc92015-11-26 05:53:00 +0000363static bool isUnderSysroot(StringRef Path) {
364 if (Config->Sysroot == "")
365 return false;
366 for (; !Path.empty(); Path = sys::path::parent_path(Path))
367 if (sys::fs::equivalent(Config->Sysroot, Path))
368 return true;
369 return false;
370}
371
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000372// Entry point. The other functions or classes are private to this file.
Rui Ueyama83cd6e02016-01-06 20:11:55 +0000373void elf2::readLinkerScript(BumpPtrAllocator *A, MemoryBufferRef MB) {
Simon Atanasyan16b0cc92015-11-26 05:53:00 +0000374 StringRef Path = MB.getBufferIdentifier();
Rui Ueyama717677a2016-02-11 21:17:59 +0000375 ScriptParser(A, MB.getBuffer(), isUnderSysroot(Path)).run();
Rui Ueyamaf7c5fbb2015-09-30 17:23:26 +0000376}