blob: f53515cc3f3c0d6ae850e16643caacd907103e72 [file] [log] [blame]
Rui Ueyama2ec34542017-04-05 05:07:391//===- ScriptParser.cpp ---------------------------------------------------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:563// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Rui Ueyama2ec34542017-04-05 05:07:396//
7//===----------------------------------------------------------------------===//
Rui Ueyama05f6b852017-04-05 05:50:088//
9// This file contains a recursive-descendent parser for linker scripts.
10// Parsed results are stored to Config and Script global objects.
11//
12//===----------------------------------------------------------------------===//
Rui Ueyama2ec34542017-04-05 05:07:3913
14#include "ScriptParser.h"
15#include "Config.h"
16#include "Driver.h"
Fangrui Songb01430a2022-02-24 03:18:2417#include "InputFiles.h"
Rui Ueyama2ec34542017-04-05 05:07:3918#include "LinkerScript.h"
Rui Ueyama2ec34542017-04-05 05:07:3919#include "OutputSections.h"
20#include "ScriptLexer.h"
Fangrui Song27bb7992022-02-08 05:53:3421#include "SymbolTable.h"
Rui Ueyama2ec34542017-04-05 05:07:3922#include "Symbols.h"
23#include "Target.h"
Alexandre Ganea83d59e02022-01-20 19:53:1824#include "lld/Common/CommonLinkerContext.h"
Rui Ueyama2ec34542017-04-05 05:07:3925#include "llvm/ADT/SmallString.h"
26#include "llvm/ADT/StringRef.h"
Rui Ueyama2ec34542017-04-05 05:07:3927#include "llvm/ADT/StringSwitch.h"
Zachary Turner264b5d92017-06-07 03:48:5628#include "llvm/BinaryFormat/ELF.h"
Rui Ueyama2ec34542017-04-05 05:07:3929#include "llvm/Support/Casting.h"
Rui Ueyama2ec34542017-04-05 05:07:3930#include "llvm/Support/ErrorHandling.h"
31#include "llvm/Support/FileSystem.h"
Isaac Richterfa1145a2020-07-27 08:49:2432#include "llvm/Support/MathExtras.h"
Rui Ueyama2ec34542017-04-05 05:07:3933#include "llvm/Support/Path.h"
Fangrui Songfe0de252022-06-26 03:25:3434#include "llvm/Support/SaveAndRestore.h"
James Henderson439341b2020-11-03 14:41:0935#include "llvm/Support/TimeProfiler.h"
Rui Ueyama2ec34542017-04-05 05:07:3936#include <cassert>
37#include <limits>
Parth Aroraebb326a2024-03-25 23:11:2138#include <optional>
Rui Ueyama2ec34542017-04-05 05:07:3939#include <vector>
40
41using namespace llvm;
42using namespace llvm::ELF;
Rui Ueyamab58079d42017-04-11 22:45:5743using namespace llvm::support::endian;
Fangrui Song07837b82020-05-15 05:18:5844using namespace lld;
45using namespace lld::elf;
Rui Ueyama2ec34542017-04-05 05:07:3946
Rui Ueyama96b3fe02017-04-05 05:08:0147namespace {
48class ScriptParser final : ScriptLexer {
Rui Ueyama2ec34542017-04-05 05:07:3949public:
Fangrui Song33204002024-09-21 18:51:0250 ScriptParser(Ctx &ctx, MemoryBufferRef mb) : ScriptLexer(ctx, mb), ctx(ctx) {}
Rui Ueyama2ec34542017-04-05 05:07:3951
52 void readLinkerScript();
53 void readVersionScript();
54 void readDynamicList();
Fangrui Songff7f97a2024-07-28 19:38:1055 void readDefsym();
Rui Ueyama2ec34542017-04-05 05:07:3956
57private:
Rui Ueyama3837f422019-07-10 05:00:3758 void addFile(StringRef path);
Rui Ueyama2ec34542017-04-05 05:07:3959
60 void readAsNeeded();
61 void readEntry();
62 void readExtern();
63 void readGroup();
64 void readInclude();
Rui Ueyama1d92aa72018-04-09 23:05:4865 void readInput();
Rui Ueyama2ec34542017-04-05 05:07:3966 void readMemory();
67 void readOutput();
68 void readOutputArch();
69 void readOutputFormat();
Fangrui Song899fdf52021-06-13 19:41:1170 void readOverwriteSections();
Rui Ueyama2ec34542017-04-05 05:07:3971 void readPhdrs();
George Rimar5f375412017-09-08 08:23:1572 void readRegionAlias();
Rui Ueyama2ec34542017-04-05 05:07:3973 void readSearchDir();
74 void readSections();
Rui Ueyamae262bb12018-08-06 21:29:4175 void readTarget();
Rui Ueyama2ec34542017-04-05 05:07:3976 void readVersion();
77 void readVersionScriptCommand();
Fangrui Song0778f5c2024-07-17 17:45:5978 void readNoCrossRefs(bool to);
Rui Ueyama2ec34542017-04-05 05:07:3979
Fangrui Song30ec2bf2024-07-27 23:19:5780 StringRef readName();
Rui Ueyama3837f422019-07-10 05:00:3781 SymbolAssignment *readSymbolAssignment(StringRef name);
82 ByteCommand *readByteCommand(StringRef tok);
Simon Atanasyanb0486052018-11-14 21:05:2083 std::array<uint8_t, 4> readFill();
Hongyu Chenb828c132024-07-20 23:35:3884 bool readSectionDirective(OutputSection *cmd, StringRef tok);
Rui Ueyama3837f422019-07-10 05:00:3785 void readSectionAddressType(OutputSection *cmd);
Fangrui Song6c814932022-03-08 19:23:4186 OutputDesc *readOverlaySectionDescription();
87 OutputDesc *readOutputSectionDescription(StringRef outSec);
Fangrui Song64038ef2021-12-27 04:12:5588 SmallVector<SectionCommand *, 0> readOverlay();
Daniel Thornburgh7e8a9022024-08-05 20:06:4589 SectionClassDesc *readSectionClassDescription();
90 StringRef readSectionClassName();
Fangrui Songa1c2ee02021-12-26 21:53:4791 SmallVector<StringRef, 0> readOutputSectionPhdrs();
Peter Smithdbd0ad32020-01-15 09:38:0092 std::pair<uint64_t, uint64_t> readInputSectionFlags();
Rui Ueyama3837f422019-07-10 05:00:3793 InputSectionDescription *readInputSectionDescription(StringRef tok);
Rui Ueyama2ec34542017-04-05 05:07:3994 StringMatcher readFilePatterns();
Fangrui Song64038ef2021-12-27 04:12:5595 SmallVector<SectionPattern, 0> readInputSectionsList();
Peter Smithdbd0ad32020-01-15 09:38:0096 InputSectionDescription *readInputSectionRules(StringRef filePattern,
97 uint64_t withFlags,
98 uint64_t withoutFlags);
Rui Ueyama2ec34542017-04-05 05:07:3999 unsigned readPhdrType();
Fangrui Song2a9aed02020-11-12 16:46:53100 SortSectionPolicy peekSortKind();
Rui Ueyama2ec34542017-04-05 05:07:39101 SortSectionPolicy readSortKind();
Rui Ueyama3837f422019-07-10 05:00:37102 SymbolAssignment *readProvideHidden(bool provide, bool hidden);
103 SymbolAssignment *readAssignment(StringRef tok);
Rui Ueyama2ec34542017-04-05 05:07:39104 void readSort();
George Rimard30a78b2018-04-25 11:16:31105 Expr readAssert();
George Rimar5fb17122017-08-03 16:05:08106 Expr readConstant();
107 Expr getPageSize();
Rui Ueyama2ec34542017-04-05 05:07:39108
Fangrui Song92b5b982020-03-06 19:49:58109 Expr readMemoryAssignment(StringRef, StringRef, StringRef);
Igor Kudrin8cdf1c12021-11-24 05:17:03110 void readMemoryAttributes(uint32_t &flags, uint32_t &invFlags,
111 uint32_t &negFlags, uint32_t &negInvFlags);
Rui Ueyama2ec34542017-04-05 05:07:39112
Rui Ueyama3837f422019-07-10 05:00:37113 Expr combine(StringRef op, Expr l, Expr r);
Rui Ueyama2ec34542017-04-05 05:07:39114 Expr readExpr();
Rui Ueyama3837f422019-07-10 05:00:37115 Expr readExpr1(Expr lhs, int minPrec);
Fangrui Song74f843d2024-07-27 23:47:17116 StringRef readParenName();
Rui Ueyama2ec34542017-04-05 05:07:39117 Expr readPrimary();
Rui Ueyama3837f422019-07-10 05:00:37118 Expr readTernary(Expr cond);
Rui Ueyama2ec34542017-04-05 05:07:39119 Expr readParenExpr();
120
121 // For parsing version script.
Fangrui Song64038ef2021-12-27 04:12:55122 SmallVector<SymbolVersion, 0> readVersionExtern();
Rui Ueyama2ec34542017-04-05 05:07:39123 void readAnonymousDeclaration();
Rui Ueyama3837f422019-07-10 05:00:37124 void readVersionDeclaration(StringRef verStr);
Rui Ueyama2ec34542017-04-05 05:07:39125
Fangrui Song64038ef2021-12-27 04:12:55126 std::pair<SmallVector<SymbolVersion, 0>, SmallVector<SymbolVersion, 0>>
Rui Ueyama2ec34542017-04-05 05:07:39127 readSymbols();
128
Fangrui Song33204002024-09-21 18:51:02129 Ctx &ctx;
130
Parth Aroraebb326a2024-03-25 23:11:21131 // If we are currently parsing a PROVIDE|PROVIDE_HIDDEN command,
132 // then this member is set to the PROVIDE symbol name.
133 std::optional<llvm::StringRef> activeProvideSym;
Rui Ueyama2ec34542017-04-05 05:07:39134};
Rui Ueyama96b3fe02017-04-05 05:08:01135} // namespace
Rui Ueyama2ec34542017-04-05 05:07:39136
Rui Ueyama3837f422019-07-10 05:00:37137static StringRef unquote(StringRef s) {
Fangrui Song8d85c962023-06-05 21:36:19138 if (s.starts_with("\""))
Rui Ueyama3837f422019-07-10 05:00:37139 return s.substr(1, s.size() - 2);
140 return s;
Rui Ueyama1e77ad12017-07-13 20:30:35141}
142
Rui Ueyama2ec34542017-04-05 05:07:39143// Some operations only support one non absolute value. Move the
144// absolute one to the right hand side for convenience.
Fangrui Song33204002024-09-21 18:51:02145static void moveAbsRight(LinkerScript &s, ExprValue &a, ExprValue &b) {
Rui Ueyama3837f422019-07-10 05:00:37146 if (a.sec == nullptr || (a.forceAbsolute && !b.isAbsolute()))
147 std::swap(a, b);
148 if (!b.isAbsolute())
Fangrui Song33204002024-09-21 18:51:02149 s.recordError(a.loc +
150 ": at least one side of the expression must be absolute");
Rui Ueyama2ec34542017-04-05 05:07:39151}
152
Fangrui Song33204002024-09-21 18:51:02153static ExprValue add(LinkerScript &s, ExprValue a, ExprValue b) {
154 moveAbsRight(s, a, b);
Rui Ueyama3837f422019-07-10 05:00:37155 return {a.sec, a.forceAbsolute, a.getSectionOffset() + b.getValue(), a.loc};
Rui Ueyama2ec34542017-04-05 05:07:39156}
157
Rui Ueyama3837f422019-07-10 05:00:37158static ExprValue sub(ExprValue a, ExprValue b) {
Rafael Espindola63a4a982017-12-26 18:11:14159 // The distance between two symbols in sections is absolute.
Rui Ueyama3837f422019-07-10 05:00:37160 if (!a.isAbsolute() && !b.isAbsolute())
161 return a.getValue() - b.getValue();
162 return {a.sec, false, a.getSectionOffset() - b.getValue(), a.loc};
Rui Ueyama2ec34542017-04-05 05:07:39163}
164
Fangrui Song33204002024-09-21 18:51:02165static ExprValue bitAnd(LinkerScript &s, ExprValue a, ExprValue b) {
166 moveAbsRight(s, a, b);
Rui Ueyama3837f422019-07-10 05:00:37167 return {a.sec, a.forceAbsolute,
168 (a.getValue() & b.getValue()) - a.getSecAddr(), a.loc};
Rui Ueyama2ec34542017-04-05 05:07:39169}
170
Fangrui Song33204002024-09-21 18:51:02171static ExprValue bitXor(LinkerScript &s, ExprValue a, ExprValue b) {
172 moveAbsRight(s, a, b);
Fangrui Songfae96102023-07-15 21:10:40173 return {a.sec, a.forceAbsolute,
174 (a.getValue() ^ b.getValue()) - a.getSecAddr(), a.loc};
175}
176
Fangrui Song33204002024-09-21 18:51:02177static ExprValue bitOr(LinkerScript &s, ExprValue a, ExprValue b) {
178 moveAbsRight(s, a, b);
Rui Ueyama3837f422019-07-10 05:00:37179 return {a.sec, a.forceAbsolute,
180 (a.getValue() | b.getValue()) - a.getSecAddr(), a.loc};
Rui Ueyama2ec34542017-04-05 05:07:39181}
182
Rui Ueyama2ec34542017-04-05 05:07:39183void ScriptParser::readDynamicList() {
184 expect("{");
Fangrui Song64038ef2021-12-27 04:12:55185 SmallVector<SymbolVersion, 0> locals;
186 SmallVector<SymbolVersion, 0> globals;
Rui Ueyama3837f422019-07-10 05:00:37187 std::tie(locals, globals) = readSymbols();
Rafael Espindolad72d97b2017-09-08 18:16:59188 expect(";");
189
Fangrui Song1978c212024-07-26 21:26:38190 StringRef tok = peek();
191 if (tok.size()) {
192 setError("EOF expected, but got " + tok);
Rafael Espindolad72d97b2017-09-08 18:16:59193 return;
194 }
Rui Ueyama3837f422019-07-10 05:00:37195 if (!locals.empty()) {
Rafael Espindolad72d97b2017-09-08 18:16:59196 setError("\"local:\" scope not supported in --dynamic-list");
197 return;
198 }
199
Rui Ueyama3837f422019-07-10 05:00:37200 for (SymbolVersion v : globals)
Fangrui Songcf57a672024-09-21 18:06:06201 ctx.arg.dynamicList.push_back(v);
Rui Ueyama2ec34542017-04-05 05:07:39202}
203
204void ScriptParser::readVersionScript() {
205 readVersionScriptCommand();
Fangrui Song1978c212024-07-26 21:26:38206 StringRef tok = peek();
207 if (tok.size())
208 setError("EOF expected, but got " + tok);
Rui Ueyama2ec34542017-04-05 05:07:39209}
210
211void ScriptParser::readVersionScriptCommand() {
212 if (consume("{")) {
213 readAnonymousDeclaration();
214 return;
215 }
216
Fangrui Song1978c212024-07-26 21:26:38217 if (atEOF())
218 setError("unexpected EOF");
219 while (peek() != "}" && !atEOF()) {
Rui Ueyama3837f422019-07-10 05:00:37220 StringRef verStr = next();
221 if (verStr == "{") {
Rui Ueyama2ec34542017-04-05 05:07:39222 setError("anonymous version definition is used in "
223 "combination with other version definitions");
224 return;
225 }
226 expect("{");
Rui Ueyama3837f422019-07-10 05:00:37227 readVersionDeclaration(verStr);
Rui Ueyama2ec34542017-04-05 05:07:39228 }
229}
230
231void ScriptParser::readVersion() {
232 expect("{");
233 readVersionScriptCommand();
234 expect("}");
235}
236
237void ScriptParser::readLinkerScript() {
238 while (!atEOF()) {
Rui Ueyama3837f422019-07-10 05:00:37239 StringRef tok = next();
Fangrui Song1978c212024-07-26 21:26:38240 if (atEOF())
241 break;
Rui Ueyama3837f422019-07-10 05:00:37242 if (tok == ";")
Rui Ueyama2ec34542017-04-05 05:07:39243 continue;
244
Rui Ueyama3837f422019-07-10 05:00:37245 if (tok == "ENTRY") {
Rui Ueyama2ec34542017-04-05 05:07:39246 readEntry();
Rui Ueyama3837f422019-07-10 05:00:37247 } else if (tok == "EXTERN") {
Rui Ueyama2ec34542017-04-05 05:07:39248 readExtern();
Rui Ueyama3837f422019-07-10 05:00:37249 } else if (tok == "GROUP") {
Rui Ueyama2ec34542017-04-05 05:07:39250 readGroup();
Rui Ueyama3837f422019-07-10 05:00:37251 } else if (tok == "INCLUDE") {
Rui Ueyama2ec34542017-04-05 05:07:39252 readInclude();
Rui Ueyama3837f422019-07-10 05:00:37253 } else if (tok == "INPUT") {
Rui Ueyama1d92aa72018-04-09 23:05:48254 readInput();
Rui Ueyama3837f422019-07-10 05:00:37255 } else if (tok == "MEMORY") {
Rui Ueyama2ec34542017-04-05 05:07:39256 readMemory();
Rui Ueyama3837f422019-07-10 05:00:37257 } else if (tok == "OUTPUT") {
Rui Ueyama2ec34542017-04-05 05:07:39258 readOutput();
Rui Ueyama3837f422019-07-10 05:00:37259 } else if (tok == "OUTPUT_ARCH") {
Rui Ueyama2ec34542017-04-05 05:07:39260 readOutputArch();
Rui Ueyama3837f422019-07-10 05:00:37261 } else if (tok == "OUTPUT_FORMAT") {
Rui Ueyama2ec34542017-04-05 05:07:39262 readOutputFormat();
Fangrui Song899fdf52021-06-13 19:41:11263 } else if (tok == "OVERWRITE_SECTIONS") {
264 readOverwriteSections();
Rui Ueyama3837f422019-07-10 05:00:37265 } else if (tok == "PHDRS") {
Rui Ueyama2ec34542017-04-05 05:07:39266 readPhdrs();
Rui Ueyama3837f422019-07-10 05:00:37267 } else if (tok == "REGION_ALIAS") {
George Rimar5f375412017-09-08 08:23:15268 readRegionAlias();
Rui Ueyama3837f422019-07-10 05:00:37269 } else if (tok == "SEARCH_DIR") {
Rui Ueyama2ec34542017-04-05 05:07:39270 readSearchDir();
Rui Ueyama3837f422019-07-10 05:00:37271 } else if (tok == "SECTIONS") {
Rui Ueyama2ec34542017-04-05 05:07:39272 readSections();
Rui Ueyama3837f422019-07-10 05:00:37273 } else if (tok == "TARGET") {
Rui Ueyamae262bb12018-08-06 21:29:41274 readTarget();
Rui Ueyama3837f422019-07-10 05:00:37275 } else if (tok == "VERSION") {
Rui Ueyama2ec34542017-04-05 05:07:39276 readVersion();
Fangrui Song0778f5c2024-07-17 17:45:59277 } else if (tok == "NOCROSSREFS") {
278 readNoCrossRefs(/*to=*/false);
279 } else if (tok == "NOCROSSREFS_TO") {
280 readNoCrossRefs(/*to=*/true);
Rui Ueyama3837f422019-07-10 05:00:37281 } else if (SymbolAssignment *cmd = readAssignment(tok)) {
Fangrui Song4629aa12024-08-22 04:23:28282 ctx.script->sectionCommands.push_back(cmd);
Rui Ueyama2ec34542017-04-05 05:07:39283 } else {
Rui Ueyama3837f422019-07-10 05:00:37284 setError("unknown directive: " + tok);
Rui Ueyama2ec34542017-04-05 05:07:39285 }
286 }
287}
288
Fangrui Songff7f97a2024-07-28 19:38:10289void ScriptParser::readDefsym() {
Fangrui Songed6c1062024-11-07 17:06:01290 if (errCount(ctx))
George Rimarc1522812018-11-26 12:29:56291 return;
Fangrui Songff7f97a2024-07-28 19:38:10292 inExpr = true;
293 StringRef name = readName();
294 expect("=");
Rui Ueyama3837f422019-07-10 05:00:37295 Expr e = readExpr();
Petr Hosek8c7e8cc2017-11-04 02:03:58296 if (!atEOF())
297 setError("EOF expected, but got " + next());
Fangrui Song43b13342024-01-22 17:09:46298 auto *cmd = make<SymbolAssignment>(
299 name, e, 0, getCurrentMB().getBufferIdentifier().str());
Fangrui Song4629aa12024-08-22 04:23:28300 ctx.script->sectionCommands.push_back(cmd);
Petr Hosek8c7e8cc2017-11-04 02:03:58301}
302
Fangrui Song0778f5c2024-07-17 17:45:59303void ScriptParser::readNoCrossRefs(bool to) {
304 expect("(");
305 NoCrossRefCommand cmd{{}, to};
Fangrui Songb32c38a2024-07-27 00:25:23306 while (auto tok = till(")"))
307 cmd.outputSections.push_back(unquote(tok));
Fangrui Song0778f5c2024-07-17 17:45:59308 if (cmd.outputSections.size() < 2)
Fangrui Songf8bae3a2024-11-07 06:19:31309 Warn(ctx) << getCurrentLocation()
310 << ": ignored with fewer than 2 output sections";
Fangrui Song0778f5c2024-07-17 17:45:59311 else
Fangrui Song4629aa12024-08-22 04:23:28312 ctx.script->noCrossRefs.push_back(std::move(cmd));
Fangrui Song0778f5c2024-07-17 17:45:59313}
314
Rui Ueyama3837f422019-07-10 05:00:37315void ScriptParser::addFile(StringRef s) {
Fangrui Songa7e8bdd2024-07-28 18:43:27316 if (curBuf.isUnderSysroot && s.starts_with("/")) {
Rui Ueyama3837f422019-07-10 05:00:37317 SmallString<128> pathData;
Fangrui Songcf57a672024-09-21 18:06:06318 StringRef path = (ctx.arg.sysroot + s).toStringRef(pathData);
Fangrui Song25087332021-06-25 19:52:39319 if (sys::fs::exists(path))
Fangrui Song2991a4e2024-11-17 06:34:12320 ctx.driver.addFile(ctx.saver.save(path), /*withLOption=*/false);
Fangrui Song25087332021-06-25 19:52:39321 else
Fangrui Songcf57a672024-09-21 18:06:06322 setError("cannot find " + s + " inside " + ctx.arg.sysroot);
Fangrui Song25087332021-06-25 19:52:39323 return;
Rui Ueyama2ec34542017-04-05 05:07:39324 }
325
Fangrui Song8d85c962023-06-05 21:36:19326 if (s.starts_with("/")) {
Fangrui Songc384ca32020-04-09 04:45:21327 // Case 1: s is an absolute path. Just open it.
Fangrui Songf596d822022-10-01 22:12:50328 ctx.driver.addFile(s, /*withLOption=*/false);
Fangrui Song8d85c962023-06-05 21:36:19329 } else if (s.starts_with("=")) {
Fangrui Songc384ca32020-04-09 04:45:21330 // Case 2: relative to the sysroot.
Fangrui Songcf57a672024-09-21 18:06:06331 if (ctx.arg.sysroot.empty())
Fangrui Songf596d822022-10-01 22:12:50332 ctx.driver.addFile(s.substr(1), /*withLOption=*/false);
Rui Ueyama2ec34542017-04-05 05:07:39333 else
Fangrui Song2991a4e2024-11-17 06:34:12334 ctx.driver.addFile(ctx.saver.save(ctx.arg.sysroot + "/" + s.substr(1)),
Fangrui Songf596d822022-10-01 22:12:50335 /*withLOption=*/false);
Fangrui Song8d85c962023-06-05 21:36:19336 } else if (s.starts_with("-l")) {
Fangrui Songc384ca32020-04-09 04:45:21337 // Case 3: search in the list of library paths.
Fangrui Songf596d822022-10-01 22:12:50338 ctx.driver.addLibrary(s.substr(2));
Rui Ueyama2ec34542017-04-05 05:07:39339 } else {
Fangrui Songc384ca32020-04-09 04:45:21340 // Case 4: s is a relative path. Search in the directory of the script file.
341 std::string filename = std::string(getCurrentMB().getBufferIdentifier());
342 StringRef directory = sys::path::parent_path(filename);
343 if (!directory.empty()) {
344 SmallString<0> path(directory);
345 sys::path::append(path, s);
346 if (sys::fs::exists(path)) {
Fangrui Songf596d822022-10-01 22:12:50347 ctx.driver.addFile(path, /*withLOption=*/false);
Fangrui Songc384ca32020-04-09 04:45:21348 return;
349 }
350 }
351 // Then search in the current working directory.
352 if (sys::fs::exists(s)) {
Fangrui Songf596d822022-10-01 22:12:50353 ctx.driver.addFile(s, /*withLOption=*/false);
Fangrui Songc384ca32020-04-09 04:45:21354 } else {
355 // Finally, search in the list of library paths.
Fangrui Song49865102024-10-06 18:27:24356 if (std::optional<std::string> path = findFromSearchPaths(ctx, s))
Fangrui Song2991a4e2024-11-17 06:34:12357 ctx.driver.addFile(ctx.saver.save(*path), /*withLOption=*/true);
Fangrui Songc384ca32020-04-09 04:45:21358 else
359 setError("unable to find " + s);
360 }
Rui Ueyama2ec34542017-04-05 05:07:39361 }
362}
363
364void ScriptParser::readAsNeeded() {
365 expect("(");
Fangrui Songcf57a672024-09-21 18:06:06366 bool orig = ctx.arg.asNeeded;
367 ctx.arg.asNeeded = true;
Fangrui Song10bb2962024-07-27 00:19:04368 while (auto tok = till(")"))
369 addFile(unquote(tok));
Fangrui Songcf57a672024-09-21 18:06:06370 ctx.arg.asNeeded = orig;
Rui Ueyama2ec34542017-04-05 05:07:39371}
372
373void ScriptParser::readEntry() {
374 // -e <symbol> takes predecence over ENTRY(<symbol>).
375 expect("(");
Fangrui Song74f843d2024-07-27 23:47:17376 StringRef name = readName();
Fangrui Songcf57a672024-09-21 18:06:06377 if (ctx.arg.entry.empty())
378 ctx.arg.entry = name;
Rui Ueyama2ec34542017-04-05 05:07:39379 expect(")");
380}
381
382void ScriptParser::readExtern() {
383 expect("(");
Fangrui Song10bb2962024-07-27 00:19:04384 while (auto tok = till(")"))
Fangrui Songcf57a672024-09-21 18:06:06385 ctx.arg.undefined.push_back(unquote(tok));
Rui Ueyama2ec34542017-04-05 05:07:39386}
387
388void ScriptParser::readGroup() {
Fangrui Songf2b01332024-10-07 00:38:35389 SaveAndRestore saved(ctx.driver.isInGroup, true);
Rui Ueyama1d92aa72018-04-09 23:05:48390 readInput();
Fangrui Songf2b01332024-10-07 00:38:35391 if (!saved.get())
392 ++ctx.driver.nextGroupId;
Rui Ueyama2ec34542017-04-05 05:07:39393}
394
395void ScriptParser::readInclude() {
Fangrui Songc89566f2024-07-27 23:27:05396 StringRef name = readName();
Fangrui Song8f72b0c2024-07-28 00:25:13397 if (!activeFilenames.insert(name).second) {
Rui Ueyama0440be42017-09-06 18:14:08398 setError("there is a cycle in linker script INCLUDEs");
399 return;
400 }
401
Fangrui Song49865102024-10-06 18:27:24402 if (std::optional<std::string> path = searchScript(ctx, name)) {
403 if (std::optional<MemoryBufferRef> mb = readFile(ctx, *path)) {
Fangrui Song1978c212024-07-26 21:26:38404 buffers.push_back(curBuf);
Fangrui Songcf57a672024-09-21 18:06:06405 curBuf = Buffer(ctx, *mb);
Fangrui Song1978c212024-07-26 21:26:38406 mbs.push_back(*mb);
407 }
Rui Ueyama2ec34542017-04-05 05:07:39408 return;
409 }
Fangrui Songc89566f2024-07-27 23:27:05410 setError("cannot find linker script " + name);
Rui Ueyama2ec34542017-04-05 05:07:39411}
412
Rui Ueyama1d92aa72018-04-09 23:05:48413void ScriptParser::readInput() {
414 expect("(");
Fangrui Song10bb2962024-07-27 00:19:04415 while (auto tok = till(")")) {
416 if (tok == "AS_NEEDED")
Rui Ueyama1d92aa72018-04-09 23:05:48417 readAsNeeded();
418 else
Fangrui Song10bb2962024-07-27 00:19:04419 addFile(unquote(tok));
Rui Ueyama1d92aa72018-04-09 23:05:48420 }
421}
422
Rui Ueyama2ec34542017-04-05 05:07:39423void ScriptParser::readOutput() {
424 // -o <file> takes predecence over OUTPUT(<file>).
425 expect("(");
Fangrui Song74f843d2024-07-27 23:47:17426 StringRef name = readName();
Fangrui Songcf57a672024-09-21 18:06:06427 if (ctx.arg.outputFile.empty())
428 ctx.arg.outputFile = name;
Rui Ueyama2ec34542017-04-05 05:07:39429 expect(")");
430}
431
432void ScriptParser::readOutputArch() {
433 // OUTPUT_ARCH is ignored for now.
434 expect("(");
Fangrui Songdbd65a02024-07-27 23:52:47435 while (till(")"))
Fangrui Song1978c212024-07-26 21:26:38436 ;
Rui Ueyama2ec34542017-04-05 05:07:39437}
438
Rui Ueyama3837f422019-07-10 05:00:37439static std::pair<ELFKind, uint16_t> parseBfdName(StringRef s) {
440 return StringSwitch<std::pair<ELFKind, uint16_t>>(s)
Rui Ueyama4f8c8222019-01-28 19:11:52441 .Case("elf32-i386", {ELF32LEKind, EM_386})
Ben Shi8527f322022-05-12 13:26:15442 .Case("elf32-avr", {ELF32LEKind, EM_AVR})
Rui Ueyama4f8c8222019-01-28 19:11:52443 .Case("elf32-iamcu", {ELF32LEKind, EM_IAMCU})
444 .Case("elf32-littlearm", {ELF32LEKind, EM_ARM})
Simi Pallipurath2f68ddc2023-02-20 13:31:45445 .Case("elf32-bigarm", {ELF32BEKind, EM_ARM})
Rui Ueyama4f8c8222019-01-28 19:11:52446 .Case("elf32-x86-64", {ELF32LEKind, EM_X86_64})
Dimitry Andric19b134c2019-01-30 06:31:52447 .Case("elf64-aarch64", {ELF64LEKind, EM_AARCH64})
Rui Ueyama4f8c8222019-01-28 19:11:52448 .Case("elf64-littleaarch64", {ELF64LEKind, EM_AARCH64})
Fangrui Song7605a9a2021-02-08 16:55:28449 .Case("elf64-bigaarch64", {ELF64BEKind, EM_AARCH64})
Rui Ueyama41341432019-02-13 18:51:15450 .Case("elf32-powerpc", {ELF32BEKind, EM_PPC})
Brandon Bergren275eb822021-01-02 18:18:05451 .Case("elf32-powerpcle", {ELF32LEKind, EM_PPC})
Rui Ueyama4f8c8222019-01-28 19:11:52452 .Case("elf64-powerpc", {ELF64BEKind, EM_PPC64})
453 .Case("elf64-powerpcle", {ELF64LEKind, EM_PPC64})
454 .Case("elf64-x86-64", {ELF64LEKind, EM_X86_64})
Rui Ueyama41341432019-02-13 18:51:15455 .Cases("elf32-tradbigmips", "elf32-bigmips", {ELF32BEKind, EM_MIPS})
Rui Ueyama4f8c8222019-01-28 19:11:52456 .Case("elf32-ntradbigmips", {ELF32BEKind, EM_MIPS})
457 .Case("elf32-tradlittlemips", {ELF32LEKind, EM_MIPS})
458 .Case("elf32-ntradlittlemips", {ELF32LEKind, EM_MIPS})
459 .Case("elf64-tradbigmips", {ELF64BEKind, EM_MIPS})
460 .Case("elf64-tradlittlemips", {ELF64LEKind, EM_MIPS})
Fangrui Song44d908d2019-06-10 08:09:55461 .Case("elf32-littleriscv", {ELF32LEKind, EM_RISCV})
462 .Case("elf64-littleriscv", {ELF64LEKind, EM_RISCV})
LemonBoyaff950e2020-04-17 14:58:15463 .Case("elf64-sparc", {ELF64BEKind, EM_SPARCV9})
LemonBoy92c61412020-12-14 17:38:12464 .Case("elf32-msp430", {ELF32LEKind, EM_MSP430})
WANG Xuerui6084ee72023-07-25 09:03:28465 .Case("elf32-loongarch", {ELF32LEKind, EM_LOONGARCH})
466 .Case("elf64-loongarch", {ELF64LEKind, EM_LOONGARCH})
Ulrich Weigandfe3406e2024-02-13 10:29:21467 .Case("elf64-s390", {ELF64BEKind, EM_S390})
Brian Cain90780362024-07-16 20:01:27468 .Cases("elf32-hexagon", "elf32-littlehexagon", {ELF32LEKind, EM_HEXAGON})
Rui Ueyama4f8c8222019-01-28 19:11:52469 .Default({ELFNoneKind, EM_NONE});
Rui Ueyamaea8cd002018-10-22 20:50:01470}
471
Fangrui Songeea34aa2021-02-08 18:34:57472// Parse OUTPUT_FORMAT(bfdname) or OUTPUT_FORMAT(default, big, little). Choose
473// big if -EB is specified, little if -EL is specified, or default if neither is
474// specified.
Rui Ueyama2ec34542017-04-05 05:07:39475void ScriptParser::readOutputFormat() {
Rui Ueyama2ec34542017-04-05 05:07:39476 expect("(");
Rui Ueyamaea8cd002018-10-22 20:50:01477
Fangrui Songc89566f2024-07-27 23:27:05478 StringRef s = readName();
Fangrui Songeea34aa2021-02-08 18:34:57479 if (!consume(")")) {
480 expect(",");
Fangrui Songc89566f2024-07-27 23:27:05481 StringRef tmp = readName();
Fangrui Songcf57a672024-09-21 18:06:06482 if (ctx.arg.optEB)
Fangrui Song6464dd22024-07-16 17:28:09483 s = tmp;
Fangrui Songeea34aa2021-02-08 18:34:57484 expect(",");
Fangrui Songc89566f2024-07-27 23:27:05485 tmp = readName();
Fangrui Songcf57a672024-09-21 18:06:06486 if (ctx.arg.optEL)
Fangrui Song6464dd22024-07-16 17:28:09487 s = tmp;
Fangrui Songeea34aa2021-02-08 18:34:57488 consume(")");
489 }
Fangrui Song6464dd22024-07-16 17:28:09490 // If more than one OUTPUT_FORMAT is specified, only the first is checked.
Fangrui Songcf57a672024-09-21 18:06:06491 if (!ctx.arg.bfdname.empty())
Fangrui Song6464dd22024-07-16 17:28:09492 return;
Fangrui Songcf57a672024-09-21 18:06:06493 ctx.arg.bfdname = s;
Fangrui Song6464dd22024-07-16 17:28:09494
495 if (s == "binary") {
Fangrui Songcf57a672024-09-21 18:06:06496 ctx.arg.oFormatBinary = true;
Fangrui Song6464dd22024-07-16 17:28:09497 return;
498 }
499
Rui Ueyama3837f422019-07-10 05:00:37500 if (s.consume_back("-freebsd"))
Fangrui Songcf57a672024-09-21 18:06:06501 ctx.arg.osabi = ELFOSABI_FREEBSD;
Rui Ueyama4f8c8222019-01-28 19:11:52502
Fangrui Songcf57a672024-09-21 18:06:06503 std::tie(ctx.arg.ekind, ctx.arg.emachine) = parseBfdName(s);
504 if (ctx.arg.emachine == EM_NONE)
505 setError("unknown output format name: " + ctx.arg.bfdname);
Rui Ueyama3837f422019-07-10 05:00:37506 if (s == "elf32-ntradlittlemips" || s == "elf32-ntradbigmips")
Fangrui Songcf57a672024-09-21 18:06:06507 ctx.arg.mipsN32Abi = true;
508 if (ctx.arg.emachine == EM_MSP430)
509 ctx.arg.osabi = ELFOSABI_STANDALONE;
Rui Ueyama2ec34542017-04-05 05:07:39510}
511
512void ScriptParser::readPhdrs() {
513 expect("{");
Fangrui Song2a893562024-07-27 00:13:37514 while (auto tok = till("}")) {
Rui Ueyama3837f422019-07-10 05:00:37515 PhdrsCommand cmd;
Fangrui Song2a893562024-07-27 00:13:37516 cmd.name = tok;
Rui Ueyama3837f422019-07-10 05:00:37517 cmd.type = readPhdrType();
Rui Ueyamab579c432017-04-05 05:40:21518
Fangrui Songed6c1062024-11-07 17:06:01519 while (!errCount(ctx) && !consume(";")) {
Rui Ueyamab579c432017-04-05 05:40:21520 if (consume("FILEHDR"))
Rui Ueyama3837f422019-07-10 05:00:37521 cmd.hasFilehdr = true;
Rui Ueyamab579c432017-04-05 05:40:21522 else if (consume("PHDRS"))
Rui Ueyama3837f422019-07-10 05:00:37523 cmd.hasPhdrs = true;
Rui Ueyamab579c432017-04-05 05:40:21524 else if (consume("AT"))
Rui Ueyama3837f422019-07-10 05:00:37525 cmd.lmaExpr = readParenExpr();
Rui Ueyamab579c432017-04-05 05:40:21526 else if (consume("FLAGS"))
Rui Ueyama3837f422019-07-10 05:00:37527 cmd.flags = readParenExpr()().getValue();
Rui Ueyamab579c432017-04-05 05:40:21528 else
529 setError("unexpected header attribute: " + next());
530 }
Rui Ueyama0ae2c242017-10-08 03:45:49531
Fangrui Song4629aa12024-08-22 04:23:28532 ctx.script->phdrsCommands.push_back(cmd);
Rui Ueyama2ec34542017-04-05 05:07:39533 }
534}
535
George Rimar5f375412017-09-08 08:23:15536void ScriptParser::readRegionAlias() {
537 expect("(");
Fangrui Songc89566f2024-07-27 23:27:05538 StringRef alias = readName();
George Rimar5f375412017-09-08 08:23:15539 expect(",");
Fangrui Song74ef53a2024-07-27 23:29:43540 StringRef name = readName();
George Rimar5f375412017-09-08 08:23:15541 expect(")");
542
Fangrui Song4629aa12024-08-22 04:23:28543 if (ctx.script->memoryRegions.count(alias))
Rui Ueyama3837f422019-07-10 05:00:37544 setError("redefinition of memory region '" + alias + "'");
Fangrui Song4629aa12024-08-22 04:23:28545 if (!ctx.script->memoryRegions.count(name))
Rui Ueyama3837f422019-07-10 05:00:37546 setError("memory region '" + name + "' is not defined");
Fangrui Song4629aa12024-08-22 04:23:28547 ctx.script->memoryRegions.insert({alias, ctx.script->memoryRegions[name]});
George Rimar5f375412017-09-08 08:23:15548}
549
Rui Ueyama2ec34542017-04-05 05:07:39550void ScriptParser::readSearchDir() {
551 expect("(");
Fangrui Songc89566f2024-07-27 23:27:05552 StringRef name = readName();
Fangrui Songcf57a672024-09-21 18:06:06553 if (!ctx.arg.nostdlib)
554 ctx.arg.searchPaths.push_back(name);
Rui Ueyama2ec34542017-04-05 05:07:39555 expect(")");
556}
557
George Rimara5824192018-06-27 08:08:12558// This reads an overlay description. Overlays are used to describe output
559// sections that use the same virtual memory range and normally would trigger
560// linker's sections sanity check failures.
561// https://sourceware.org/binutils/docs/ld/Overlay-Description.html#Overlay-Description
Fangrui Song64038ef2021-12-27 04:12:55562SmallVector<SectionCommand *, 0> ScriptParser::readOverlay() {
Fangrui Song7c89b202024-01-09 00:12:49563 Expr addrExpr;
564 if (consume(":")) {
Fangrui Song33204002024-09-21 18:51:02565 addrExpr = [s = ctx.script] { return s->getDot(); };
Fangrui Song7c89b202024-01-09 00:12:49566 } else {
567 addrExpr = readExpr();
568 expect(":");
569 }
570 // When AT is omitted, LMA should equal VMA. script->getDot() when evaluating
571 // lmaExpr will ensure this, even if the start address is specified.
Fangrui Song33204002024-09-21 18:51:02572 Expr lmaExpr = consume("AT") ? readParenExpr()
573 : [s = ctx.script] { return s->getDot(); };
George Rimara5824192018-06-27 08:08:12574 expect("{");
575
Fangrui Song64038ef2021-12-27 04:12:55576 SmallVector<SectionCommand *, 0> v;
Rui Ueyama3837f422019-07-10 05:00:37577 OutputSection *prev = nullptr;
Fangrui Songed6c1062024-11-07 17:06:01578 while (!errCount(ctx) && !consume("}")) {
George Rimara5824192018-06-27 08:08:12579 // VA is the same for all sections. The LMAs are consecutive in memory
580 // starting from the base load address specified.
Fangrui Song6c814932022-03-08 19:23:41581 OutputDesc *osd = readOverlaySectionDescription();
582 osd->osec.addrExpr = addrExpr;
Fangrui Song7c89b202024-01-09 00:12:49583 if (prev) {
Fangrui Song6c814932022-03-08 19:23:41584 osd->osec.lmaExpr = [=] { return prev->getLMA() + prev->size; };
Fangrui Song7c89b202024-01-09 00:12:49585 } else {
Fangrui Song6c814932022-03-08 19:23:41586 osd->osec.lmaExpr = lmaExpr;
Fangrui Song7c89b202024-01-09 00:12:49587 // Use first section address for subsequent sections as initial addrExpr
588 // can be DOT. Ensure the first section, even if empty, is not discarded.
589 osd->osec.usedInExpression = true;
590 addrExpr = [=]() -> ExprValue { return {&osd->osec, false, 0, ""}; };
591 }
Fangrui Song6c814932022-03-08 19:23:41592 v.push_back(osd);
593 prev = &osd->osec;
George Rimara5824192018-06-27 08:08:12594 }
595
596 // According to the specification, at the end of the overlay, the location
597 // counter should be equal to the overlay base address plus size of the
598 // largest section seen in the overlay.
599 // Here we want to create the Dot assignment command to achieve that.
Rui Ueyama3837f422019-07-10 05:00:37600 Expr moveDot = [=] {
601 uint64_t max = 0;
Fangrui Song7051aee2021-11-26 04:24:23602 for (SectionCommand *cmd : v)
Fangrui Song6c814932022-03-08 19:23:41603 max = std::max(max, cast<OutputDesc>(cmd)->osec.size);
Rui Ueyama3837f422019-07-10 05:00:37604 return addrExpr().getValue() + max;
George Rimara5824192018-06-27 08:08:12605 };
Fangrui Song65a15a52023-09-09 21:46:51606 v.push_back(make<SymbolAssignment>(".", moveDot, 0, getCurrentLocation()));
Rui Ueyama3837f422019-07-10 05:00:37607 return v;
George Rimara5824192018-06-27 08:08:12608}
609
Daniel Thornburgh7e8a9022024-08-05 20:06:45610SectionClassDesc *ScriptParser::readSectionClassDescription() {
611 StringRef name = readSectionClassName();
612 SectionClassDesc *desc = make<SectionClassDesc>(name);
Fangrui Song4629aa12024-08-22 04:23:28613 if (!ctx.script->sectionClasses.insert({CachedHashStringRef(name), desc})
614 .second)
Daniel Thornburgh7e8a9022024-08-05 20:06:45615 setError("section class '" + name + "' already defined");
616 expect("{");
617 while (auto tok = till("}")) {
618 if (tok == "(" || tok == ")") {
619 setError("expected filename pattern");
620 } else if (peek() == "(") {
621 InputSectionDescription *isd = readInputSectionDescription(tok);
622 if (!isd->classRef.empty())
623 setError("section class '" + name + "' references class '" +
624 isd->classRef + "'");
625 desc->sc.commands.push_back(isd);
626 }
627 }
628 return desc;
629}
630
631StringRef ScriptParser::readSectionClassName() {
632 expect("(");
633 StringRef name = unquote(next());
634 expect(")");
635 return name;
636}
637
Fangrui Song899fdf52021-06-13 19:41:11638void ScriptParser::readOverwriteSections() {
639 expect("{");
Fangrui Song2a893562024-07-27 00:13:37640 while (auto tok = till("}"))
Fangrui Song4629aa12024-08-22 04:23:28641 ctx.script->overwriteSections.push_back(readOutputSectionDescription(tok));
Fangrui Song899fdf52021-06-13 19:41:11642}
643
Rui Ueyama2ec34542017-04-05 05:07:39644void ScriptParser::readSections() {
Rui Ueyama2ec34542017-04-05 05:07:39645 expect("{");
Fangrui Song64038ef2021-12-27 04:12:55646 SmallVector<SectionCommand *, 0> v;
Fangrui Song2a893562024-07-27 00:13:37647 while (auto tok = till("}")) {
Rui Ueyama3837f422019-07-10 05:00:37648 if (tok == "OVERLAY") {
Fangrui Song7051aee2021-11-26 04:24:23649 for (SectionCommand *cmd : readOverlay())
Rui Ueyama3837f422019-07-10 05:00:37650 v.push_back(cmd);
George Rimara5824192018-06-27 08:08:12651 continue;
Daniel Thornburgh7e8a9022024-08-05 20:06:45652 }
653 if (tok == "CLASS") {
654 v.push_back(readSectionClassDescription());
655 continue;
656 }
657 if (tok == "INCLUDE") {
Rui Ueyama2e9d40d2018-10-12 17:07:32658 readInclude();
659 continue;
George Rimara5824192018-06-27 08:08:12660 }
661
Fangrui Song7051aee2021-11-26 04:24:23662 if (SectionCommand *cmd = readAssignment(tok))
Rui Ueyama3837f422019-07-10 05:00:37663 v.push_back(cmd);
George Rimard30a78b2018-04-25 11:16:31664 else
Fangrui Song49dfbc62023-07-05 22:08:53665 v.push_back(readOutputSectionDescription(tok));
Rui Ueyama2ec34542017-04-05 05:07:39666 }
Fangrui Song5a449802022-05-04 08:10:45667
668 // If DATA_SEGMENT_RELRO_END is absent, for sections after DATA_SEGMENT_ALIGN,
669 // the relro fields should be cleared.
Fangrui Song4629aa12024-08-22 04:23:28670 if (!ctx.script->seenRelroEnd)
Fangrui Song5a449802022-05-04 08:10:45671 for (SectionCommand *cmd : v)
672 if (auto *osd = dyn_cast<OutputDesc>(cmd))
673 osd->osec.relro = false;
674
Fangrui Song4629aa12024-08-22 04:23:28675 ctx.script->sectionCommands.insert(ctx.script->sectionCommands.end(),
676 v.begin(), v.end());
George Rimar9e2c8a92018-03-08 14:54:38677
Fangrui Song7c426fb2020-02-10 23:58:29678 if (atEOF() || !consume("INSERT")) {
Fangrui Song4629aa12024-08-22 04:23:28679 ctx.script->hasSectionsCommand = true;
George Rimar9e2c8a92018-03-08 14:54:38680 return;
681 }
682
Fangrui Song7c426fb2020-02-10 23:58:29683 bool isAfter = false;
684 if (consume("AFTER"))
685 isAfter = true;
686 else if (!consume("BEFORE"))
687 setError("expected AFTER/BEFORE, but got '" + next() + "'");
Fangrui Song9c16a4a2024-07-28 00:34:37688 StringRef where = readName();
Fangrui Songa1c2ee02021-12-26 21:53:47689 SmallVector<StringRef, 0> names;
Fangrui Song7051aee2021-11-26 04:24:23690 for (SectionCommand *cmd : v)
Fangrui Song6c814932022-03-08 19:23:41691 if (auto *os = dyn_cast<OutputDesc>(cmd))
692 names.push_back(os->osec.name);
Fangrui Song03051f72021-06-30 18:35:50693 if (!names.empty())
Fangrui Song4629aa12024-08-22 04:23:28694 ctx.script->insertCommands.push_back({std::move(names), isAfter, where});
Rui Ueyama2ec34542017-04-05 05:07:39695}
696
Rui Ueyamae262bb12018-08-06 21:29:41697void ScriptParser::readTarget() {
698 // TARGET(foo) is an alias for "--format foo". Unlike GNU linkers,
699 // we accept only a limited set of BFD names (i.e. "elf" or "binary")
700 // for --format. We recognize only /^elf/ and "binary" in the linker
701 // script as well.
702 expect("(");
Fangrui Songc89566f2024-07-27 23:27:05703 StringRef tok = readName();
Rui Ueyamae262bb12018-08-06 21:29:41704 expect(")");
705
Fangrui Song8d85c962023-06-05 21:36:19706 if (tok.starts_with("elf"))
Fangrui Songcf57a672024-09-21 18:06:06707 ctx.arg.formatBinary = false;
Rui Ueyama3837f422019-07-10 05:00:37708 else if (tok == "binary")
Fangrui Songcf57a672024-09-21 18:06:06709 ctx.arg.formatBinary = true;
Rui Ueyamae262bb12018-08-06 21:29:41710 else
Rui Ueyama3837f422019-07-10 05:00:37711 setError("unknown target: " + tok);
Rui Ueyamae262bb12018-08-06 21:29:41712}
713
Rui Ueyama3837f422019-07-10 05:00:37714static int precedence(StringRef op) {
715 return StringSwitch<int>(op)
Fangrui Songfae96102023-07-15 21:10:40716 .Cases("*", "/", "%", 11)
717 .Cases("+", "-", 10)
718 .Cases("<<", ">>", 9)
719 .Cases("<", "<=", ">", ">=", 8)
720 .Cases("==", "!=", 7)
721 .Case("&", 6)
722 .Case("^", 5)
Fangrui Songd479b2e2022-06-25 20:47:32723 .Case("|", 4)
724 .Case("&&", 3)
725 .Case("||", 2)
Fangrui Songb0d6dd32022-06-25 20:48:52726 .Case("?", 1)
Rui Ueyama2ec34542017-04-05 05:07:39727 .Default(-1);
728}
729
730StringMatcher ScriptParser::readFilePatterns() {
Thomas Preud'hommec42fe242020-01-10 16:56:07731 StringMatcher Matcher;
Fangrui Song10bb2962024-07-27 00:19:04732 while (auto tok = till(")"))
733 Matcher.addPattern(SingleStringMatcher(tok));
Thomas Preud'hommec42fe242020-01-10 16:56:07734 return Matcher;
Rui Ueyama2ec34542017-04-05 05:07:39735}
736
Fangrui Song2a9aed02020-11-12 16:46:53737SortSectionPolicy ScriptParser::peekSortKind() {
738 return StringSwitch<SortSectionPolicy>(peek())
Justin Cady447aa482023-03-06 14:35:39739 .Case("REVERSE", SortSectionPolicy::Reverse)
Fangrui Song2a9aed02020-11-12 16:46:53740 .Cases("SORT", "SORT_BY_NAME", SortSectionPolicy::Name)
741 .Case("SORT_BY_ALIGNMENT", SortSectionPolicy::Alignment)
742 .Case("SORT_BY_INIT_PRIORITY", SortSectionPolicy::Priority)
743 .Case("SORT_NONE", SortSectionPolicy::None)
744 .Default(SortSectionPolicy::Default);
745}
746
Rui Ueyama2ec34542017-04-05 05:07:39747SortSectionPolicy ScriptParser::readSortKind() {
Fangrui Song2a9aed02020-11-12 16:46:53748 SortSectionPolicy ret = peekSortKind();
749 if (ret != SortSectionPolicy::Default)
750 skip();
751 return ret;
Rui Ueyama2ec34542017-04-05 05:07:39752}
753
Rui Ueyama03fc8d12017-04-05 19:20:54754// Reads SECTIONS command contents in the following form:
755//
756// <contents> ::= <elem>*
757// <elem> ::= <exclude>? <glob-pattern>
758// <exclude> ::= "EXCLUDE_FILE" "(" <glob-pattern>+ ")"
759//
760// For example,
761//
762// *(.foo EXCLUDE_FILE (a.o) .bar EXCLUDE_FILE (b.o) .baz)
763//
764// is parsed as ".foo", ".bar" with "a.o", and ".baz" with "b.o".
765// The semantics of that is section .foo in any file, section .bar in
766// any file but a.o, and section .baz in any file but b.o.
Fangrui Song64038ef2021-12-27 04:12:55767SmallVector<SectionPattern, 0> ScriptParser::readInputSectionsList() {
768 SmallVector<SectionPattern, 0> ret;
Fangrui Songed6c1062024-11-07 17:06:01769 while (!errCount(ctx) && peek() != ")") {
Rui Ueyama3837f422019-07-10 05:00:37770 StringMatcher excludeFilePat;
Rui Ueyama2ec34542017-04-05 05:07:39771 if (consume("EXCLUDE_FILE")) {
772 expect("(");
Rui Ueyama3837f422019-07-10 05:00:37773 excludeFilePat = readFilePatterns();
Rui Ueyama2ec34542017-04-05 05:07:39774 }
775
Thomas Preud'hommec42fe242020-01-10 16:56:07776 StringMatcher SectionMatcher;
Fangrui Song2a9aed02020-11-12 16:46:53777 // Break if the next token is ), EXCLUDE_FILE, or SORT*.
Fangrui Songed6c1062024-11-07 17:06:01778 while (!errCount(ctx) && peekSortKind() == SortSectionPolicy::Default) {
Fangrui Song551e20d2024-03-07 01:19:59779 StringRef s = peek();
780 if (s == ")" || s == "EXCLUDE_FILE")
781 break;
782 // Detect common mistakes when certain non-wildcard meta characters are
783 // used without a closing ')'.
784 if (!s.empty() && strchr("(){}", s[0])) {
785 skip();
786 setError("section pattern is expected");
787 break;
788 }
Fangrui Songc89566f2024-07-27 23:27:05789 SectionMatcher.addPattern(readName());
Fangrui Song551e20d2024-03-07 01:19:59790 }
Rui Ueyama2ec34542017-04-05 05:07:39791
Thomas Preud'hommec42fe242020-01-10 16:56:07792 if (!SectionMatcher.empty())
793 ret.push_back({std::move(excludeFilePat), std::move(SectionMatcher)});
Fangrui Song2a9aed02020-11-12 16:46:53794 else if (excludeFilePat.empty())
795 break;
Rui Ueyama2ec34542017-04-05 05:07:39796 else
797 setError("section pattern is expected");
798 }
Rui Ueyama3837f422019-07-10 05:00:37799 return ret;
Rui Ueyama2ec34542017-04-05 05:07:39800}
801
802// Reads contents of "SECTIONS" directive. That directive contains a
803// list of glob patterns for input sections. The grammar is as follows.
804//
805// <patterns> ::= <section-list>
806// | <sort> "(" <section-list> ")"
807// | <sort> "(" <sort> "(" <section-list> ")" ")"
808//
809// <sort> ::= "SORT" | "SORT_BY_NAME" | "SORT_BY_ALIGNMENT"
810// | "SORT_BY_INIT_PRIORITY" | "SORT_NONE"
811//
812// <section-list> is parsed by readInputSectionsList().
813InputSectionDescription *
Peter Smithdbd0ad32020-01-15 09:38:00814ScriptParser::readInputSectionRules(StringRef filePattern, uint64_t withFlags,
815 uint64_t withoutFlags) {
816 auto *cmd =
817 make<InputSectionDescription>(filePattern, withFlags, withoutFlags);
Rui Ueyama2ec34542017-04-05 05:07:39818 expect("(");
819
Fangrui Song1978c212024-07-26 21:26:38820 while (peek() != ")" && !atEOF()) {
Rui Ueyama3837f422019-07-10 05:00:37821 SortSectionPolicy outer = readSortKind();
822 SortSectionPolicy inner = SortSectionPolicy::Default;
Fangrui Song64038ef2021-12-27 04:12:55823 SmallVector<SectionPattern, 0> v;
Rui Ueyama3837f422019-07-10 05:00:37824 if (outer != SortSectionPolicy::Default) {
Rui Ueyama2ec34542017-04-05 05:07:39825 expect("(");
Rui Ueyama3837f422019-07-10 05:00:37826 inner = readSortKind();
827 if (inner != SortSectionPolicy::Default) {
Rui Ueyama2ec34542017-04-05 05:07:39828 expect("(");
Rui Ueyama3837f422019-07-10 05:00:37829 v = readInputSectionsList();
Rui Ueyama2ec34542017-04-05 05:07:39830 expect(")");
831 } else {
Rui Ueyama3837f422019-07-10 05:00:37832 v = readInputSectionsList();
Rui Ueyama2ec34542017-04-05 05:07:39833 }
834 expect(")");
835 } else {
Rui Ueyama3837f422019-07-10 05:00:37836 v = readInputSectionsList();
Rui Ueyama2ec34542017-04-05 05:07:39837 }
838
Rui Ueyama3837f422019-07-10 05:00:37839 for (SectionPattern &pat : v) {
840 pat.sortInner = inner;
841 pat.sortOuter = outer;
Rui Ueyama2ec34542017-04-05 05:07:39842 }
843
Rui Ueyama3837f422019-07-10 05:00:37844 std::move(v.begin(), v.end(), std::back_inserter(cmd->sectionPatterns));
Rui Ueyama2ec34542017-04-05 05:07:39845 }
Fangrui Song1978c212024-07-26 21:26:38846 expect(")");
Rui Ueyama3837f422019-07-10 05:00:37847 return cmd;
Rui Ueyama2ec34542017-04-05 05:07:39848}
849
850InputSectionDescription *
Rui Ueyama3837f422019-07-10 05:00:37851ScriptParser::readInputSectionDescription(StringRef tok) {
Rui Ueyama2ec34542017-04-05 05:07:39852 // Input section wildcard can be surrounded by KEEP.
853 // https://sourceware.org/binutils/docs/ld/Input-Section-Keep.html#Input-Section-Keep
Peter Smithdbd0ad32020-01-15 09:38:00854 uint64_t withFlags = 0;
855 uint64_t withoutFlags = 0;
Rui Ueyama3837f422019-07-10 05:00:37856 if (tok == "KEEP") {
Rui Ueyama2ec34542017-04-05 05:07:39857 expect("(");
Peter Smithdbd0ad32020-01-15 09:38:00858 if (consume("INPUT_SECTION_FLAGS"))
859 std::tie(withFlags, withoutFlags) = readInputSectionFlags();
Daniel Thornburgh7e8a9022024-08-05 20:06:45860
861 tok = next();
862 InputSectionDescription *cmd;
863 if (tok == "CLASS")
864 cmd = make<InputSectionDescription>(StringRef{}, withFlags, withoutFlags,
865 readSectionClassName());
866 else
867 cmd = readInputSectionRules(tok, withFlags, withoutFlags);
Rui Ueyama2ec34542017-04-05 05:07:39868 expect(")");
Fangrui Song4629aa12024-08-22 04:23:28869 ctx.script->keptSections.push_back(cmd);
Rui Ueyama3837f422019-07-10 05:00:37870 return cmd;
Rui Ueyama2ec34542017-04-05 05:07:39871 }
Peter Smithdbd0ad32020-01-15 09:38:00872 if (tok == "INPUT_SECTION_FLAGS") {
873 std::tie(withFlags, withoutFlags) = readInputSectionFlags();
874 tok = next();
875 }
Daniel Thornburgh7e8a9022024-08-05 20:06:45876 if (tok == "CLASS")
877 return make<InputSectionDescription>(StringRef{}, withFlags, withoutFlags,
878 readSectionClassName());
Peter Smithdbd0ad32020-01-15 09:38:00879 return readInputSectionRules(tok, withFlags, withoutFlags);
Rui Ueyama2ec34542017-04-05 05:07:39880}
881
882void ScriptParser::readSort() {
883 expect("(");
884 expect("CONSTRUCTORS");
885 expect(")");
886}
887
George Rimard30a78b2018-04-25 11:16:31888Expr ScriptParser::readAssert() {
Rui Ueyama2ec34542017-04-05 05:07:39889 expect("(");
Rui Ueyama3837f422019-07-10 05:00:37890 Expr e = readExpr();
Rui Ueyama2ec34542017-04-05 05:07:39891 expect(",");
Fangrui Songc89566f2024-07-27 23:27:05892 StringRef msg = readName();
Rui Ueyama2ec34542017-04-05 05:07:39893 expect(")");
Rui Ueyamab579c432017-04-05 05:40:21894
Fangrui Song9b058bb2024-11-07 06:33:51895 return [=, s = ctx.script, &ctx = ctx]() -> ExprValue {
Rui Ueyama3837f422019-07-10 05:00:37896 if (!e().getValue())
Fangrui Song9b058bb2024-11-07 06:33:51897 Err(ctx) << msg;
Fangrui Song33204002024-09-21 18:51:02898 return s->getDot();
Rui Ueyama2ec34542017-04-05 05:07:39899 };
900}
901
Fangrui Song66f8ac82022-02-17 20:10:58902#define ECase(X) \
903 { #X, X }
904constexpr std::pair<const char *, unsigned> typeMap[] = {
905 ECase(SHT_PROGBITS), ECase(SHT_NOTE), ECase(SHT_NOBITS),
906 ECase(SHT_INIT_ARRAY), ECase(SHT_FINI_ARRAY), ECase(SHT_PREINIT_ARRAY),
907};
908#undef ECase
909
George Rimara46d08e2018-08-28 08:39:21910// Tries to read the special directive for an output section definition which
Fangrui Song66f8ac82022-02-17 20:10:58911// can be one of following: "(NOLOAD)", "(COPY)", "(INFO)", "(OVERLAY)", and
912// "(TYPE=<value>)".
Hongyu Chenb828c132024-07-20 23:35:38913bool ScriptParser::readSectionDirective(OutputSection *cmd, StringRef tok) {
914 if (tok != "NOLOAD" && tok != "COPY" && tok != "INFO" && tok != "OVERLAY" &&
915 tok != "TYPE")
George Rimara46d08e2018-08-28 08:39:21916 return false;
917
George Rimara46d08e2018-08-28 08:39:21918 if (consume("NOLOAD")) {
Matt Schultefdc41aa2020-03-28 16:54:06919 cmd->type = SHT_NOBITS;
Fangrui Song66f8ac82022-02-17 20:10:58920 cmd->typeIsSet = true;
921 } else if (consume("TYPE")) {
922 expect("=");
923 StringRef value = peek();
924 auto it = llvm::find_if(typeMap, [=](auto e) { return e.first == value; });
925 if (it != std::end(typeMap)) {
926 // The value is a recognized literal SHT_*.
927 cmd->type = it->second;
928 skip();
Fangrui Song8d85c962023-06-05 21:36:19929 } else if (value.starts_with("SHT_")) {
Fangrui Song66f8ac82022-02-17 20:10:58930 setError("unknown section type " + value);
931 } else {
932 // Otherwise, read an expression.
933 cmd->type = readExpr()().getValue();
934 }
935 cmd->typeIsSet = true;
George Rimara46d08e2018-08-28 08:39:21936 } else {
937 skip(); // This is "COPY", "INFO" or "OVERLAY".
Rui Ueyama3837f422019-07-10 05:00:37938 cmd->nonAlloc = true;
George Rimara46d08e2018-08-28 08:39:21939 }
940 expect(")");
941 return true;
942}
943
George Rimar1c08e9f2018-02-16 10:42:58944// Reads an expression and/or the special directive for an output
945// section definition. Directive is one of following: "(NOLOAD)",
946// "(COPY)", "(INFO)" or "(OVERLAY)".
Rui Ueyama3271d372017-06-08 19:47:16947//
948// An output section name can be followed by an address expression
George Rimar1c08e9f2018-02-16 10:42:58949// and/or directive. This grammar is not LL(1) because "(" can be
George Rimar97f4d152018-02-16 10:46:50950// interpreted as either the beginning of some expression or beginning
George Rimar1c08e9f2018-02-16 10:42:58951// of directive.
Rui Ueyama3271d372017-06-08 19:47:16952//
953// https://sourceware.org/binutils/docs/ld/Output-Section-Address.html
954// https://sourceware.org/binutils/docs/ld/Output-Section-Type.html
Rui Ueyama3837f422019-07-10 05:00:37955void ScriptParser::readSectionAddressType(OutputSection *cmd) {
Hongyu Chenb828c132024-07-20 23:35:38956 if (consume("(")) {
Fangrui Song28045ce2024-07-20 21:13:02957 // Temporarily set inExpr to support TYPE=<value> without spaces.
958 SaveAndRestore saved(inExpr, true);
Hongyu Chenb828c132024-07-20 23:35:38959 if (readSectionDirective(cmd, peek()))
Fangrui Song28045ce2024-07-20 21:13:02960 return;
Hongyu Chenb828c132024-07-20 23:35:38961 cmd->addrExpr = readExpr();
962 expect(")");
963 } else {
964 cmd->addrExpr = readExpr();
Fangrui Song28045ce2024-07-20 21:13:02965 }
Fangrui Song28045ce2024-07-20 21:13:02966
Hongyu Chenb828c132024-07-20 23:35:38967 if (consume("(")) {
Fangrui Song28045ce2024-07-20 21:13:02968 SaveAndRestore saved(inExpr, true);
Hongyu Chenb828c132024-07-20 23:35:38969 StringRef tok = peek();
970 if (!readSectionDirective(cmd, tok))
971 setError("unknown section directive: " + tok);
Fangrui Song28045ce2024-07-20 21:13:02972 }
Rui Ueyama3271d372017-06-08 19:47:16973}
974
Fangrui Songe24457a2024-11-15 06:17:10975static Expr checkAlignment(Ctx &ctx, Expr e, std::string &loc) {
976 return [=, &ctx] {
Rui Ueyama3837f422019-07-10 05:00:37977 uint64_t alignment = std::max((uint64_t)1, e().getValue());
978 if (!isPowerOf2_64(alignment)) {
Fangrui Song09c2c5e2024-11-07 06:04:52979 ErrAlways(ctx) << loc << ": alignment must be power of 2";
George Rimarf22ec9d2017-10-25 14:50:51980 return (uint64_t)1; // Return a dummy value.
981 }
Rui Ueyama3837f422019-07-10 05:00:37982 return alignment;
George Rimarf22ec9d2017-10-25 14:50:51983 };
984}
985
Fangrui Song6c814932022-03-08 19:23:41986OutputDesc *ScriptParser::readOverlaySectionDescription() {
Fangrui Songe6895152024-07-27 23:33:18987 OutputDesc *osd =
Fangrui Song4629aa12024-08-22 04:23:28988 ctx.script->createOutputSection(readName(), getCurrentLocation());
Fangrui Song6c814932022-03-08 19:23:41989 osd->osec.inOverlay = true;
George Rimara5824192018-06-27 08:08:12990 expect("{");
Hongyu Chenf1a7d142024-07-27 21:16:12991 while (auto tok = till("}")) {
Peter Smithdbd0ad32020-01-15 09:38:00992 uint64_t withFlags = 0;
993 uint64_t withoutFlags = 0;
Hongyu Chenf1a7d142024-07-27 21:16:12994 if (tok == "INPUT_SECTION_FLAGS") {
Peter Smithdbd0ad32020-01-15 09:38:00995 std::tie(withFlags, withoutFlags) = readInputSectionFlags();
Hongyu Chenf1a7d142024-07-27 21:16:12996 tok = till("");
997 }
Daniel Thornburgh7e8a9022024-08-05 20:06:45998 if (tok == "CLASS")
999 osd->osec.commands.push_back(make<InputSectionDescription>(
1000 StringRef{}, withFlags, withoutFlags, readSectionClassName()));
1001 else
1002 osd->osec.commands.push_back(
1003 readInputSectionRules(tok, withFlags, withoutFlags));
Peter Smithdbd0ad32020-01-15 09:38:001004 }
Peter Smithe16af8a2023-05-11 11:00:191005 osd->osec.phdrs = readOutputSectionPhdrs();
Fangrui Song6c814932022-03-08 19:23:411006 return osd;
George Rimara5824192018-06-27 08:08:121007}
1008
Fangrui Song6c814932022-03-08 19:23:411009OutputDesc *ScriptParser::readOutputSectionDescription(StringRef outSec) {
Fangrui Songd60ef932023-02-03 19:03:001010 OutputDesc *cmd =
Fangrui Song4629aa12024-08-22 04:23:281011 ctx.script->createOutputSection(unquote(outSec), getCurrentLocation());
Fangrui Song6c814932022-03-08 19:23:411012 OutputSection *osec = &cmd->osec;
Fangrui Song5a449802022-05-04 08:10:451013 // Maybe relro. Will reset to false if DATA_SEGMENT_RELRO_END is absent.
Fangrui Song4629aa12024-08-22 04:23:281014 osec->relro = ctx.script->seenDataAlign && !ctx.script->seenRelroEnd;
Rui Ueyama2ec34542017-04-05 05:07:391015
Fangrui Song4629aa12024-08-22 04:23:281016 size_t symbolsReferenced = ctx.script->referencedSymbols.size();
George Rimarc4df6702018-03-01 12:27:041017
Rui Ueyama3271d372017-06-08 19:47:161018 if (peek() != ":")
Fangrui Song6c814932022-03-08 19:23:411019 readSectionAddressType(osec);
Rui Ueyama2ec34542017-04-05 05:07:391020 expect(":");
1021
Rui Ueyama3837f422019-07-10 05:00:371022 std::string location = getCurrentLocation();
Rui Ueyama2ec34542017-04-05 05:07:391023 if (consume("AT"))
Fangrui Song6c814932022-03-08 19:23:411024 osec->lmaExpr = readParenExpr();
Rui Ueyama2ec34542017-04-05 05:07:391025 if (consume("ALIGN"))
Fangrui Songe24457a2024-11-15 06:17:101026 osec->alignExpr = checkAlignment(ctx, readParenExpr(), location);
Rui Ueyama2ec34542017-04-05 05:07:391027 if (consume("SUBALIGN"))
Fangrui Songe24457a2024-11-15 06:17:101028 osec->subalignExpr = checkAlignment(ctx, readParenExpr(), location);
Rui Ueyama2ec34542017-04-05 05:07:391029
1030 // Parse constraints.
1031 if (consume("ONLY_IF_RO"))
Fangrui Song6c814932022-03-08 19:23:411032 osec->constraint = ConstraintKind::ReadOnly;
Rui Ueyama2ec34542017-04-05 05:07:391033 if (consume("ONLY_IF_RW"))
Fangrui Song6c814932022-03-08 19:23:411034 osec->constraint = ConstraintKind::ReadWrite;
Rui Ueyama2ec34542017-04-05 05:07:391035 expect("{");
1036
Fangrui Song2a893562024-07-27 00:13:371037 while (auto tok = till("}")) {
Rui Ueyama3837f422019-07-10 05:00:371038 if (tok == ";") {
Rui Ueyama2ec34542017-04-05 05:07:391039 // Empty commands are allowed. Do nothing here.
Rui Ueyama3837f422019-07-10 05:00:371040 } else if (SymbolAssignment *assign = readAssignment(tok)) {
Fangrui Song6c814932022-03-08 19:23:411041 osec->commands.push_back(assign);
Rui Ueyama3837f422019-07-10 05:00:371042 } else if (ByteCommand *data = readByteCommand(tok)) {
Fangrui Song6c814932022-03-08 19:23:411043 osec->commands.push_back(data);
Rui Ueyama3837f422019-07-10 05:00:371044 } else if (tok == "CONSTRUCTORS") {
Rui Ueyama2ec34542017-04-05 05:07:391045 // CONSTRUCTORS is a keyword to make the linker recognize C++ ctors/dtors
1046 // by name. This is for very old file formats such as ECOFF/XCOFF.
1047 // For ELF, we should ignore.
Rui Ueyama3837f422019-07-10 05:00:371048 } else if (tok == "FILL") {
George Rimar0810f162019-07-04 14:17:311049 // We handle the FILL command as an alias for =fillexp section attribute,
1050 // which is different from what GNU linkers do.
1051 // https://sourceware.org/binutils/docs/ld/Output-Section-Data.html
Georgii Rymarbb7d2b12020-02-16 11:17:261052 if (peek() != "(")
1053 setError("( expected, but got " + peek());
Fangrui Song6c814932022-03-08 19:23:411054 osec->filler = readFill();
Rui Ueyama3837f422019-07-10 05:00:371055 } else if (tok == "SORT") {
Rui Ueyama2ec34542017-04-05 05:07:391056 readSort();
Rui Ueyama3837f422019-07-10 05:00:371057 } else if (tok == "INCLUDE") {
Rui Ueyama2e9d40d2018-10-12 17:07:321058 readInclude();
Fangrui Song177fd722022-05-13 18:06:011059 } else if (tok == "(" || tok == ")") {
1060 setError("expected filename pattern");
Rui Ueyama2ec34542017-04-05 05:07:391061 } else if (peek() == "(") {
Fangrui Song6c814932022-03-08 19:23:411062 osec->commands.push_back(readInputSectionDescription(tok));
Rui Ueyama2ec34542017-04-05 05:07:391063 } else {
George Rimarf49fe212018-12-06 08:34:521064 // We have a file name and no input sections description. It is not a
1065 // commonly used syntax, but still acceptable. In that case, all sections
1066 // from the file will be included.
Peter Smithdbd0ad32020-01-15 09:38:001067 // FIXME: GNU ld permits INPUT_SECTION_FLAGS to be used here. We do not
1068 // handle this case here as it will already have been matched by the
1069 // case above.
Rui Ueyama3837f422019-07-10 05:00:371070 auto *isd = make<InputSectionDescription>(tok);
Thomas Preud'hommec42fe242020-01-10 16:56:071071 isd->sectionPatterns.push_back({{}, StringMatcher("*")});
Fangrui Song6c814932022-03-08 19:23:411072 osec->commands.push_back(isd);
Rui Ueyama2ec34542017-04-05 05:07:391073 }
1074 }
1075
1076 if (consume(">"))
Fangrui Song0d8bc102024-07-27 23:39:141077 osec->memoryRegionName = std::string(readName());
Rui Ueyama2ec34542017-04-05 05:07:391078
George Rimar5d01a8b2018-01-12 09:07:351079 if (consume("AT")) {
1080 expect(">");
Fangrui Song0d8bc102024-07-27 23:39:141081 osec->lmaRegionName = std::string(readName());
George Rimar5d01a8b2018-01-12 09:07:351082 }
1083
Fangrui Song6c814932022-03-08 19:23:411084 if (osec->lmaExpr && !osec->lmaRegionName.empty())
Fangrui Song09c2c5e2024-11-07 06:04:521085 ErrAlways(ctx) << "section can't have both LMA and a load region";
George Rimar5d01a8b2018-01-12 09:07:351086
Fangrui Song6c814932022-03-08 19:23:411087 osec->phdrs = readOutputSectionPhdrs();
Rui Ueyama2ec34542017-04-05 05:07:391088
Fangrui Song8d85c962023-06-05 21:36:191089 if (peek() == "=" || peek().starts_with("=")) {
Rui Ueyama3837f422019-07-10 05:00:371090 inExpr = true;
George Rimar0810f162019-07-04 14:17:311091 consume("=");
Fangrui Song6c814932022-03-08 19:23:411092 osec->filler = readFill();
Rui Ueyama3837f422019-07-10 05:00:371093 inExpr = false;
George Rimar0810f162019-07-04 14:17:311094 }
Rui Ueyama2ec34542017-04-05 05:07:391095
1096 // Consume optional comma following output section command.
1097 consume(",");
1098
Fangrui Song4629aa12024-08-22 04:23:281099 if (ctx.script->referencedSymbols.size() > symbolsReferenced)
Fangrui Song6c814932022-03-08 19:23:411100 osec->expressionsUseSymbols = true;
Rui Ueyama3837f422019-07-10 05:00:371101 return cmd;
Rui Ueyama2ec34542017-04-05 05:07:391102}
1103
George Rimar0810f162019-07-04 14:17:311104// Reads a `=<fillexp>` expression and returns its value as a big-endian number.
Rui Ueyama2ec34542017-04-05 05:07:391105// https://sourceware.org/binutils/docs/ld/Output-Section-Fill.html
George Rimar0810f162019-07-04 14:17:311106// We do not support using symbols in such expressions.
Rui Ueyama2ec34542017-04-05 05:07:391107//
Rui Ueyama8acbf1c2017-04-13 23:40:191108// When reading a hexstring, ld.bfd handles it as a blob of arbitrary
1109// size, while ld.gold always handles it as a 32-bit big-endian number.
1110// We are compatible with ld.gold because it's easier to implement.
Georgii Rymarbb7d2b12020-02-16 11:17:261111// Also, we require that expressions with operators must be wrapped into
1112// round brackets. We did it to resolve the ambiguity when parsing scripts like:
1113// SECTIONS { .foo : { ... } =120+3 /DISCARD/ : { ... } }
George Rimar0810f162019-07-04 14:17:311114std::array<uint8_t, 4> ScriptParser::readFill() {
Georgii Rymarbb7d2b12020-02-16 11:17:261115 uint64_t value = readPrimary()().val;
Rui Ueyama3837f422019-07-10 05:00:371116 if (value > UINT32_MAX)
George Rimar0810f162019-07-04 14:17:311117 setError("filler expression result does not fit 32-bit: 0x" +
Rui Ueyama3837f422019-07-10 05:00:371118 Twine::utohexstr(value));
Rui Ueyamab58079d42017-04-11 22:45:571119
Rui Ueyama3837f422019-07-10 05:00:371120 std::array<uint8_t, 4> buf;
1121 write32be(buf.data(), (uint32_t)value);
1122 return buf;
Rui Ueyama2ec34542017-04-05 05:07:391123}
1124
Rui Ueyama3837f422019-07-10 05:00:371125SymbolAssignment *ScriptParser::readProvideHidden(bool provide, bool hidden) {
Rui Ueyama2ec34542017-04-05 05:07:391126 expect("(");
Fangrui Song30ec2bf2024-07-27 23:19:571127 StringRef name = readName(), eq = peek();
Fangrui Song21bf6bb2022-06-26 03:26:471128 if (eq != "=") {
1129 setError("= expected, but got " + next());
Hongyu Chenf1a7d142024-07-27 21:16:121130 while (till(")"))
Fangrui Song21bf6bb2022-06-26 03:26:471131 ;
1132 return nullptr;
1133 }
Parth Aroraebb326a2024-03-25 23:11:211134 llvm::SaveAndRestore saveActiveProvideSym(activeProvideSym);
1135 if (provide)
1136 activeProvideSym = name;
Fangrui Song21bf6bb2022-06-26 03:26:471137 SymbolAssignment *cmd = readSymbolAssignment(name);
Rui Ueyama3837f422019-07-10 05:00:371138 cmd->provide = provide;
1139 cmd->hidden = hidden;
Rui Ueyama2ec34542017-04-05 05:07:391140 expect(")");
Rui Ueyama3837f422019-07-10 05:00:371141 return cmd;
Rui Ueyama2ec34542017-04-05 05:07:391142}
1143
Fangrui Song1978c212024-07-26 21:26:381144// Replace whitespace sequence (including \n) with one single space. The output
1145// is used by -Map.
1146static void squeezeSpaces(std::string &str) {
1147 char prev = '\0';
1148 auto it = str.begin();
1149 for (char c : str)
1150 if (!isSpace(c) || (c = ' ') != prev)
1151 *it++ = prev = c;
1152 str.erase(it, str.end());
1153}
1154
Rui Ueyama3837f422019-07-10 05:00:371155SymbolAssignment *ScriptParser::readAssignment(StringRef tok) {
George Rimard30a78b2018-04-25 11:16:311156 // Assert expression returns Dot, so this is equal to ".=."
Rui Ueyama3837f422019-07-10 05:00:371157 if (tok == "ASSERT")
Fangrui Song65a15a52023-09-09 21:46:511158 return make<SymbolAssignment>(".", readAssert(), 0, getCurrentLocation());
George Rimard30a78b2018-04-25 11:16:311159
Fangrui Song1978c212024-07-26 21:26:381160 const char *oldS = prevTok.data();
Rui Ueyama3837f422019-07-10 05:00:371161 SymbolAssignment *cmd = nullptr;
Fangrui Song4629aa12024-08-22 04:23:281162 bool savedSeenRelroEnd = ctx.script->seenRelroEnd;
Fangrui Song0a0effd2022-06-26 05:22:591163 const StringRef op = peek();
Fangrui Songedcc60e2024-07-27 23:04:381164 {
Jan Svobodaabf0c6c2022-12-02 21:36:041165 SaveAndRestore saved(inExpr, true);
Fangrui Songedcc60e2024-07-27 23:04:381166 if (op.starts_with("=")) {
1167 // Support = followed by an expression without whitespace.
Fangrui Song30ec2bf2024-07-27 23:19:571168 cmd = readSymbolAssignment(unquote(tok));
Fangrui Songedcc60e2024-07-27 23:04:381169 } else if ((op.size() == 2 && op[1] == '=' && strchr("+-*/&^|", op[0])) ||
1170 op == "<<=" || op == ">>=") {
Fangrui Song30ec2bf2024-07-27 23:19:571171 cmd = readSymbolAssignment(unquote(tok));
Fangrui Songedcc60e2024-07-27 23:04:381172 } else if (tok == "PROVIDE") {
1173 cmd = readProvideHidden(true, false);
1174 } else if (tok == "HIDDEN") {
1175 cmd = readProvideHidden(false, true);
1176 } else if (tok == "PROVIDE_HIDDEN") {
1177 cmd = readProvideHidden(true, true);
1178 }
Fangrui Songfe0de252022-06-26 03:25:341179 }
George Rimare88b76a2018-04-05 11:25:581180
Rui Ueyama3837f422019-07-10 05:00:371181 if (cmd) {
Fangrui Song4629aa12024-08-22 04:23:281182 cmd->dataSegmentRelroEnd = !savedSeenRelroEnd && ctx.script->seenRelroEnd;
Fangrui Song1978c212024-07-26 21:26:381183 cmd->commandString = StringRef(oldS, curTok.data() - oldS).str();
1184 squeezeSpaces(cmd->commandString);
George Rimare88b76a2018-04-05 11:25:581185 expect(";");
Rui Ueyama2ec34542017-04-05 05:07:391186 }
Rui Ueyama3837f422019-07-10 05:00:371187 return cmd;
Rui Ueyama2ec34542017-04-05 05:07:391188}
1189
Fangrui Song30ec2bf2024-07-27 23:19:571190StringRef ScriptParser::readName() { return unquote(next()); }
1191
Rui Ueyama3837f422019-07-10 05:00:371192SymbolAssignment *ScriptParser::readSymbolAssignment(StringRef name) {
Rui Ueyama3837f422019-07-10 05:00:371193 StringRef op = next();
Fangrui Song0a0effd2022-06-26 05:22:591194 assert(op == "=" || op == "*=" || op == "/=" || op == "+=" || op == "-=" ||
Fangrui Songfae96102023-07-15 21:10:401195 op == "&=" || op == "^=" || op == "|=" || op == "<<=" || op == ">>=");
Fangrui Song1bd5df72023-09-16 00:52:481196 // Note: GNU ld does not support %=.
Rui Ueyama3837f422019-07-10 05:00:371197 Expr e = readExpr();
Fangrui Song0a0effd2022-06-26 05:22:591198 if (op != "=") {
Rui Ueyama3837f422019-07-10 05:00:371199 std::string loc = getCurrentLocation();
Fangrui Song09c2c5e2024-11-07 06:04:521200 e = [=, s = ctx.script, c = op[0], &ctx = ctx]() -> ExprValue {
Fangrui Song33204002024-09-21 18:51:021201 ExprValue lhs = s->getSymbolValue(name, loc);
Fangrui Song0a0effd2022-06-26 05:22:591202 switch (c) {
1203 case '*':
1204 return lhs.getValue() * e().getValue();
1205 case '/':
1206 if (uint64_t rv = e().getValue())
1207 return lhs.getValue() / rv;
Fangrui Song09c2c5e2024-11-07 06:04:521208 ErrAlways(ctx) << loc << ": division by zero";
Fangrui Song0a0effd2022-06-26 05:22:591209 return 0;
1210 case '+':
Fangrui Song33204002024-09-21 18:51:021211 return add(*s, lhs, e());
Fangrui Song0a0effd2022-06-26 05:22:591212 case '-':
1213 return sub(lhs, e());
1214 case '<':
Fangrui Songdaba24e2023-06-15 17:34:331215 return lhs.getValue() << e().getValue() % 64;
Fangrui Song0a0effd2022-06-26 05:22:591216 case '>':
Fangrui Songdaba24e2023-06-15 17:34:331217 return lhs.getValue() >> e().getValue() % 64;
Fangrui Song0a0effd2022-06-26 05:22:591218 case '&':
1219 return lhs.getValue() & e().getValue();
Fangrui Songfae96102023-07-15 21:10:401220 case '^':
1221 return lhs.getValue() ^ e().getValue();
Fangrui Song0a0effd2022-06-26 05:22:591222 case '|':
1223 return lhs.getValue() | e().getValue();
1224 default:
1225 llvm_unreachable("");
1226 }
1227 };
Rui Ueyama2ec34542017-04-05 05:07:391228 }
Fangrui Song65a15a52023-09-09 21:46:511229 return make<SymbolAssignment>(name, e, ctx.scriptSymOrderCounter++,
1230 getCurrentLocation());
Rui Ueyama2ec34542017-04-05 05:07:391231}
1232
1233// This is an operator-precedence parser to parse a linker
1234// script expression.
1235Expr ScriptParser::readExpr() {
1236 // Our lexer is context-aware. Set the in-expression bit so that
1237 // they apply different tokenization rules.
Fangrui Songefa833d2024-07-20 21:36:551238 SaveAndRestore saved(inExpr, true);
Rui Ueyama3837f422019-07-10 05:00:371239 Expr e = readExpr1(readPrimary(), 0);
Rui Ueyama3837f422019-07-10 05:00:371240 return e;
Rui Ueyama2ec34542017-04-05 05:07:391241}
1242
Rui Ueyama3837f422019-07-10 05:00:371243Expr ScriptParser::combine(StringRef op, Expr l, Expr r) {
1244 if (op == "+")
Fangrui Song33204002024-09-21 18:51:021245 return [=, s = ctx.script] { return add(*s, l(), r()); };
Rui Ueyama3837f422019-07-10 05:00:371246 if (op == "-")
1247 return [=] { return sub(l(), r()); };
1248 if (op == "*")
1249 return [=] { return l().getValue() * r().getValue(); };
1250 if (op == "/") {
1251 std::string loc = getCurrentLocation();
Fangrui Song09c2c5e2024-11-07 06:04:521252 return [=, &ctx = ctx]() -> uint64_t {
Rui Ueyama3837f422019-07-10 05:00:371253 if (uint64_t rv = r().getValue())
1254 return l().getValue() / rv;
Fangrui Song09c2c5e2024-11-07 06:04:521255 ErrAlways(ctx) << loc << ": division by zero";
Rui Ueyama067617f2018-03-05 23:50:451256 return 0;
George Rimar7b91e212018-03-05 10:02:441257 };
1258 }
Rui Ueyama3837f422019-07-10 05:00:371259 if (op == "%") {
1260 std::string loc = getCurrentLocation();
Fangrui Song09c2c5e2024-11-07 06:04:521261 return [=, &ctx = ctx]() -> uint64_t {
Rui Ueyama3837f422019-07-10 05:00:371262 if (uint64_t rv = r().getValue())
1263 return l().getValue() % rv;
Fangrui Song09c2c5e2024-11-07 06:04:521264 ErrAlways(ctx) << loc << ": modulo by zero";
Rui Ueyama067617f2018-03-05 23:50:451265 return 0;
George Rimar7b91e212018-03-05 10:02:441266 };
1267 }
Rui Ueyama3837f422019-07-10 05:00:371268 if (op == "<<")
Fangrui Songdaba24e2023-06-15 17:34:331269 return [=] { return l().getValue() << r().getValue() % 64; };
Rui Ueyama3837f422019-07-10 05:00:371270 if (op == ">>")
Fangrui Songdaba24e2023-06-15 17:34:331271 return [=] { return l().getValue() >> r().getValue() % 64; };
Rui Ueyama3837f422019-07-10 05:00:371272 if (op == "<")
1273 return [=] { return l().getValue() < r().getValue(); };
1274 if (op == ">")
1275 return [=] { return l().getValue() > r().getValue(); };
1276 if (op == ">=")
1277 return [=] { return l().getValue() >= r().getValue(); };
1278 if (op == "<=")
1279 return [=] { return l().getValue() <= r().getValue(); };
1280 if (op == "==")
1281 return [=] { return l().getValue() == r().getValue(); };
1282 if (op == "!=")
1283 return [=] { return l().getValue() != r().getValue(); };
1284 if (op == "||")
1285 return [=] { return l().getValue() || r().getValue(); };
1286 if (op == "&&")
1287 return [=] { return l().getValue() && r().getValue(); };
1288 if (op == "&")
Fangrui Song33204002024-09-21 18:51:021289 return [=, s = ctx.script] { return bitAnd(*s, l(), r()); };
Fangrui Songfae96102023-07-15 21:10:401290 if (op == "^")
Fangrui Song33204002024-09-21 18:51:021291 return [=, s = ctx.script] { return bitXor(*s, l(), r()); };
Rui Ueyama3837f422019-07-10 05:00:371292 if (op == "|")
Fangrui Song33204002024-09-21 18:51:021293 return [=, s = ctx.script] { return bitOr(*s, l(), r()); };
Rui Ueyama2ec34542017-04-05 05:07:391294 llvm_unreachable("invalid operator");
1295}
1296
1297// This is a part of the operator-precedence parser. This function
1298// assumes that the remaining token stream starts with an operator.
Rui Ueyama3837f422019-07-10 05:00:371299Expr ScriptParser::readExpr1(Expr lhs, int minPrec) {
Fangrui Songed6c1062024-11-07 17:06:011300 while (!atEOF() && !errCount(ctx)) {
Rui Ueyama2ec34542017-04-05 05:07:391301 // Read an operator and an expression.
Rui Ueyama3837f422019-07-10 05:00:371302 StringRef op1 = peek();
1303 if (precedence(op1) < minPrec)
Rui Ueyama2ec34542017-04-05 05:07:391304 break;
1305 skip();
Fangrui Songefa833d2024-07-20 21:36:551306 if (op1 == "?")
1307 return readTernary(lhs);
Rui Ueyama3837f422019-07-10 05:00:371308 Expr rhs = readPrimary();
Rui Ueyama2ec34542017-04-05 05:07:391309
1310 // Evaluate the remaining part of the expression first if the
1311 // next operator has greater precedence than the previous one.
1312 // For example, if we have read "+" and "3", and if the next
1313 // operator is "*", then we'll evaluate 3 * ... part first.
1314 while (!atEOF()) {
Rui Ueyama3837f422019-07-10 05:00:371315 StringRef op2 = peek();
1316 if (precedence(op2) <= precedence(op1))
Rui Ueyama2ec34542017-04-05 05:07:391317 break;
Rui Ueyama3837f422019-07-10 05:00:371318 rhs = readExpr1(rhs, precedence(op2));
Rui Ueyama2ec34542017-04-05 05:07:391319 }
1320
Rui Ueyama3837f422019-07-10 05:00:371321 lhs = combine(op1, lhs, rhs);
Rui Ueyama2ec34542017-04-05 05:07:391322 }
Rui Ueyama3837f422019-07-10 05:00:371323 return lhs;
Rui Ueyama2ec34542017-04-05 05:07:391324}
1325
George Rimar5fb17122017-08-03 16:05:081326Expr ScriptParser::getPageSize() {
Rui Ueyama3837f422019-07-10 05:00:371327 std::string location = getCurrentLocation();
Fangrui Song33204002024-09-21 18:51:021328 return [=, &ctx = this->ctx]() -> uint64_t {
Fangrui Songb4feb262024-08-22 06:53:361329 if (ctx.target)
Fangrui Songcf57a672024-09-21 18:06:061330 return ctx.arg.commonPageSize;
Fangrui Song09c2c5e2024-11-07 06:04:521331 ErrAlways(ctx) << location << ": unable to calculate page size";
George Rimar5fb17122017-08-03 16:05:081332 return 4096; // Return a dummy value.
1333 };
1334}
1335
1336Expr ScriptParser::readConstant() {
Fangrui Song74f843d2024-07-27 23:47:171337 StringRef s = readParenName();
Rui Ueyama3837f422019-07-10 05:00:371338 if (s == "COMMONPAGESIZE")
George Rimar5fb17122017-08-03 16:05:081339 return getPageSize();
Rui Ueyama3837f422019-07-10 05:00:371340 if (s == "MAXPAGESIZE")
Fangrui Song33204002024-09-21 18:51:021341 return [&ctx = this->ctx] { return ctx.arg.maxPageSize; };
Rui Ueyama3837f422019-07-10 05:00:371342 setError("unknown constant: " + s);
George Rimarb068b032018-03-01 12:36:011343 return [] { return 0; };
Rui Ueyama2ec34542017-04-05 05:07:391344}
1345
Rui Ueyama5c650882017-04-05 23:22:111346// Parses Tok as an integer. It recognizes hexadecimal (prefixed with
1347// "0x" or suffixed with "H") and decimal numbers. Decimal numbers may
1348// have "K" (Ki) or "M" (Mi) suffixes.
Fangrui Song4191fda2022-11-27 03:19:151349static std::optional<uint64_t> parseInt(StringRef tok) {
Rui Ueyama2ec34542017-04-05 05:07:391350 // Hexadecimal
Rui Ueyama3837f422019-07-10 05:00:371351 uint64_t val;
Kazu Hirataed1539c2023-05-16 17:12:421352 if (tok.starts_with_insensitive("0x")) {
Rui Ueyama3837f422019-07-10 05:00:371353 if (!to_integer(tok.substr(2), val, 16))
Fangrui Song4191fda2022-11-27 03:19:151354 return std::nullopt;
Rui Ueyama3837f422019-07-10 05:00:371355 return val;
Rui Ueyama40920162017-10-11 19:30:391356 }
Kazu Hirataed1539c2023-05-16 17:12:421357 if (tok.ends_with_insensitive("H")) {
Rui Ueyama3837f422019-07-10 05:00:371358 if (!to_integer(tok.drop_back(), val, 16))
Fangrui Song4191fda2022-11-27 03:19:151359 return std::nullopt;
Rui Ueyama3837f422019-07-10 05:00:371360 return val;
Rui Ueyama40920162017-10-11 19:30:391361 }
Rui Ueyama2ec34542017-04-05 05:07:391362
1363 // Decimal
Kazu Hirataed1539c2023-05-16 17:12:421364 if (tok.ends_with_insensitive("K")) {
Rui Ueyama3837f422019-07-10 05:00:371365 if (!to_integer(tok.drop_back(), val, 10))
Fangrui Song4191fda2022-11-27 03:19:151366 return std::nullopt;
Rui Ueyama3837f422019-07-10 05:00:371367 return val * 1024;
Rui Ueyama2ec34542017-04-05 05:07:391368 }
Kazu Hirataed1539c2023-05-16 17:12:421369 if (tok.ends_with_insensitive("M")) {
Rui Ueyama3837f422019-07-10 05:00:371370 if (!to_integer(tok.drop_back(), val, 10))
Fangrui Song4191fda2022-11-27 03:19:151371 return std::nullopt;
Rui Ueyama3837f422019-07-10 05:00:371372 return val * 1024 * 1024;
Rui Ueyama5c650882017-04-05 23:22:111373 }
Rui Ueyama3837f422019-07-10 05:00:371374 if (!to_integer(tok, val, 10))
Fangrui Song4191fda2022-11-27 03:19:151375 return std::nullopt;
Rui Ueyama3837f422019-07-10 05:00:371376 return val;
Rui Ueyama2ec34542017-04-05 05:07:391377}
1378
Rui Ueyama3837f422019-07-10 05:00:371379ByteCommand *ScriptParser::readByteCommand(StringRef tok) {
1380 int size = StringSwitch<int>(tok)
Rui Ueyama2ec34542017-04-05 05:07:391381 .Case("BYTE", 1)
1382 .Case("SHORT", 2)
1383 .Case("LONG", 4)
1384 .Case("QUAD", 8)
1385 .Default(-1);
Rui Ueyama3837f422019-07-10 05:00:371386 if (size == -1)
Rui Ueyama2ec34542017-04-05 05:07:391387 return nullptr;
George Rimar84bcabc2018-03-15 09:16:401388
Fangrui Song1978c212024-07-26 21:26:381389 const char *oldS = prevTok.data();
Rui Ueyama3837f422019-07-10 05:00:371390 Expr e = readParenExpr();
Fangrui Song1978c212024-07-26 21:26:381391 std::string commandString = StringRef(oldS, curBuf.s.data() - oldS).str();
1392 squeezeSpaces(commandString);
1393 return make<ByteCommand>(e, size, std::move(commandString));
Rui Ueyama2ec34542017-04-05 05:07:391394}
1395
Fangrui Song4191fda2022-11-27 03:19:151396static std::optional<uint64_t> parseFlag(StringRef tok) {
1397 if (std::optional<uint64_t> asInt = parseInt(tok))
Peter Smithdbd0ad32020-01-15 09:38:001398 return asInt;
1399#define CASE_ENT(enum) #enum, ELF::enum
Fangrui Song4191fda2022-11-27 03:19:151400 return StringSwitch<std::optional<uint64_t>>(tok)
Peter Smithdbd0ad32020-01-15 09:38:001401 .Case(CASE_ENT(SHF_WRITE))
1402 .Case(CASE_ENT(SHF_ALLOC))
1403 .Case(CASE_ENT(SHF_EXECINSTR))
1404 .Case(CASE_ENT(SHF_MERGE))
1405 .Case(CASE_ENT(SHF_STRINGS))
1406 .Case(CASE_ENT(SHF_INFO_LINK))
1407 .Case(CASE_ENT(SHF_LINK_ORDER))
1408 .Case(CASE_ENT(SHF_OS_NONCONFORMING))
1409 .Case(CASE_ENT(SHF_GROUP))
1410 .Case(CASE_ENT(SHF_TLS))
1411 .Case(CASE_ENT(SHF_COMPRESSED))
1412 .Case(CASE_ENT(SHF_EXCLUDE))
1413 .Case(CASE_ENT(SHF_ARM_PURECODE))
Kazu Hiratac68af422022-12-03 07:12:361414 .Default(std::nullopt);
Peter Smithdbd0ad32020-01-15 09:38:001415#undef CASE_ENT
1416}
1417
1418// Reads the '(' <flags> ')' list of section flags in
1419// INPUT_SECTION_FLAGS '(' <flags> ')' in the
1420// following form:
1421// <flags> ::= <flag>
1422// | <flags> & flag
1423// <flag> ::= Recognized Flag Name, or Integer value of flag.
1424// If the first character of <flag> is a ! then this means without flag,
1425// otherwise with flag.
1426// Example: SHF_EXECINSTR & !SHF_WRITE means with flag SHF_EXECINSTR and
1427// without flag SHF_WRITE.
1428std::pair<uint64_t, uint64_t> ScriptParser::readInputSectionFlags() {
Fangrui Songc89566f2024-07-27 23:27:051429 uint64_t withFlags = 0;
1430 uint64_t withoutFlags = 0;
1431 expect("(");
Fangrui Songed6c1062024-11-07 17:06:011432 while (!errCount(ctx)) {
Fangrui Songc89566f2024-07-27 23:27:051433 StringRef tok = readName();
Peter Smithdbd0ad32020-01-15 09:38:001434 bool without = tok.consume_front("!");
Fangrui Song4191fda2022-11-27 03:19:151435 if (std::optional<uint64_t> flag = parseFlag(tok)) {
Peter Smithdbd0ad32020-01-15 09:38:001436 if (without)
1437 withoutFlags |= *flag;
1438 else
1439 withFlags |= *flag;
1440 } else {
1441 setError("unrecognised flag: " + tok);
1442 }
1443 if (consume(")"))
1444 break;
1445 if (!consume("&")) {
1446 next();
1447 setError("expected & or )");
1448 }
1449 }
1450 return std::make_pair(withFlags, withoutFlags);
1451}
1452
Fangrui Song74f843d2024-07-27 23:47:171453StringRef ScriptParser::readParenName() {
Rui Ueyama2ec34542017-04-05 05:07:391454 expect("(");
Rui Ueyama3837f422019-07-10 05:00:371455 bool orig = inExpr;
1456 inExpr = false;
Fangrui Song74f843d2024-07-27 23:47:171457 StringRef tok = readName();
Rui Ueyama3837f422019-07-10 05:00:371458 inExpr = orig;
Rui Ueyama2ec34542017-04-05 05:07:391459 expect(")");
Rui Ueyama3837f422019-07-10 05:00:371460 return tok;
Rui Ueyama2ec34542017-04-05 05:07:391461}
1462
Fangrui Song33204002024-09-21 18:51:021463static void checkIfExists(LinkerScript &script, const OutputSection &osec,
1464 StringRef location) {
1465 if (osec.location.empty() && script.errorOnMissingSection)
1466 script.recordError(location + ": undefined section " + osec.name);
Rafael Espindola05c4f672017-06-01 01:16:501467}
1468
Fangrui Songe4f385d2021-03-11 17:34:361469static bool isValidSymbolName(StringRef s) {
1470 auto valid = [](char c) {
1471 return isAlnum(c) || c == '$' || c == '.' || c == '_';
1472 };
1473 return !s.empty() && !isDigit(s[0]) && llvm::all_of(s, valid);
1474}
1475
Rui Ueyama2ec34542017-04-05 05:07:391476Expr ScriptParser::readPrimary() {
1477 if (peek() == "(")
1478 return readParenExpr();
1479
Rui Ueyama5c650882017-04-05 23:22:111480 if (consume("~")) {
Rui Ueyama3837f422019-07-10 05:00:371481 Expr e = readPrimary();
1482 return [=] { return ~e().getValue(); };
Rui Ueyama2ec34542017-04-05 05:07:391483 }
Hafiz Abid Qadeer6f1d9542017-08-10 15:25:471484 if (consume("!")) {
Rui Ueyama3837f422019-07-10 05:00:371485 Expr e = readPrimary();
1486 return [=] { return !e().getValue(); };
Hafiz Abid Qadeer6f1d9542017-08-10 15:25:471487 }
Rui Ueyama5c650882017-04-05 23:22:111488 if (consume("-")) {
Rui Ueyama3837f422019-07-10 05:00:371489 Expr e = readPrimary();
1490 return [=] { return -e().getValue(); };
Rui Ueyama2ec34542017-04-05 05:07:391491 }
1492
Rui Ueyama3837f422019-07-10 05:00:371493 StringRef tok = next();
1494 std::string location = getCurrentLocation();
Rui Ueyama5c650882017-04-05 23:22:111495
Rui Ueyama2ec34542017-04-05 05:07:391496 // Built-in functions are parsed here.
1497 // https://sourceware.org/binutils/docs/ld/Builtin-Functions.html.
Rui Ueyama3837f422019-07-10 05:00:371498 if (tok == "ABSOLUTE") {
1499 Expr inner = readParenExpr();
Rui Ueyama2ec34542017-04-05 05:07:391500 return [=] {
Rui Ueyama3837f422019-07-10 05:00:371501 ExprValue i = inner();
1502 i.forceAbsolute = true;
1503 return i;
Rui Ueyama2ec34542017-04-05 05:07:391504 };
1505 }
Rui Ueyama3837f422019-07-10 05:00:371506 if (tok == "ADDR") {
Fangrui Song74f843d2024-07-27 23:47:171507 StringRef name = readParenName();
Fangrui Song4629aa12024-08-22 04:23:281508 OutputSection *osec = &ctx.script->getOrCreateOutputSection(name)->osec;
Fangrui Song9e9c86f2022-02-28 19:19:001509 osec->usedInExpression = true;
Fangrui Song33204002024-09-21 18:51:021510 return [=, s = ctx.script]() -> ExprValue {
1511 checkIfExists(*s, *osec, location);
Fangrui Song9e9c86f2022-02-28 19:19:001512 return {osec, false, 0, location};
George Rimar41c7ab42017-06-07 08:54:431513 };
Rui Ueyama2ec34542017-04-05 05:07:391514 }
Rui Ueyama3837f422019-07-10 05:00:371515 if (tok == "ALIGN") {
Rui Ueyama2ec34542017-04-05 05:07:391516 expect("(");
Rui Ueyama3837f422019-07-10 05:00:371517 Expr e = readExpr();
George Rimarf22ec9d2017-10-25 14:50:511518 if (consume(")")) {
Fangrui Songe24457a2024-11-15 06:17:101519 e = checkAlignment(ctx, e, location);
Fangrui Song33204002024-09-21 18:51:021520 return [=, s = ctx.script] {
1521 return alignToPowerOf2(s->getDot(), e().getValue());
1522 };
George Rimarf22ec9d2017-10-25 14:50:511523 }
Rui Ueyamab579c432017-04-05 05:40:211524 expect(",");
Fangrui Songe24457a2024-11-15 06:17:101525 Expr e2 = checkAlignment(ctx, readExpr(), location);
Rui Ueyama2ec34542017-04-05 05:07:391526 expect(")");
Petr Hosek3c6de1a2017-05-30 03:18:281527 return [=] {
Rui Ueyama3837f422019-07-10 05:00:371528 ExprValue v = e();
1529 v.alignment = e2().getValue();
1530 return v;
Petr Hosek3c6de1a2017-05-30 03:18:281531 };
Rui Ueyama2ec34542017-04-05 05:07:391532 }
Rui Ueyama3837f422019-07-10 05:00:371533 if (tok == "ALIGNOF") {
Fangrui Song74f843d2024-07-27 23:47:171534 StringRef name = readParenName();
Fangrui Song4629aa12024-08-22 04:23:281535 OutputSection *osec = &ctx.script->getOrCreateOutputSection(name)->osec;
Fangrui Song33204002024-09-21 18:51:021536 return [=, s = ctx.script] {
1537 checkIfExists(*s, *osec, location);
Guillaume Chatelet08e2a762022-12-01 16:19:561538 return osec->addralign;
Rui Ueyama617e2f92017-10-08 02:27:021539 };
Rui Ueyama2ec34542017-04-05 05:07:391540 }
Rui Ueyama3837f422019-07-10 05:00:371541 if (tok == "ASSERT")
George Rimard30a78b2018-04-25 11:16:311542 return readAssert();
Rui Ueyama3837f422019-07-10 05:00:371543 if (tok == "CONSTANT")
George Rimar5fb17122017-08-03 16:05:081544 return readConstant();
Rui Ueyama3837f422019-07-10 05:00:371545 if (tok == "DATA_SEGMENT_ALIGN") {
Rui Ueyama2ec34542017-04-05 05:07:391546 expect("(");
Rui Ueyama3837f422019-07-10 05:00:371547 Expr e = readExpr();
Rui Ueyama2ec34542017-04-05 05:07:391548 expect(",");
1549 readExpr();
1550 expect(")");
Fangrui Song4629aa12024-08-22 04:23:281551 ctx.script->seenDataAlign = true;
Fangrui Song33204002024-09-21 18:51:021552 return [=, s = ctx.script] {
Fangrui Song85cfd912022-07-24 18:20:491553 uint64_t align = std::max(uint64_t(1), e().getValue());
Fangrui Song33204002024-09-21 18:51:021554 return (s->getDot() + align - 1) & -align;
George Rimar60833f62017-07-28 09:27:491555 };
Rui Ueyama2ec34542017-04-05 05:07:391556 }
Rui Ueyama3837f422019-07-10 05:00:371557 if (tok == "DATA_SEGMENT_END") {
Rui Ueyama2ec34542017-04-05 05:07:391558 expect("(");
1559 expect(".");
1560 expect(")");
Fangrui Song33204002024-09-21 18:51:021561 return [s = ctx.script] { return s->getDot(); };
Rui Ueyama2ec34542017-04-05 05:07:391562 }
Rui Ueyama3837f422019-07-10 05:00:371563 if (tok == "DATA_SEGMENT_RELRO_END") {
Rui Ueyama2ec34542017-04-05 05:07:391564 // GNU linkers implements more complicated logic to handle
1565 // DATA_SEGMENT_RELRO_END. We instead ignore the arguments and
1566 // just align to the next page boundary for simplicity.
1567 expect("(");
1568 readExpr();
1569 expect(",");
1570 readExpr();
1571 expect(")");
Fangrui Song4629aa12024-08-22 04:23:281572 ctx.script->seenRelroEnd = true;
Fangrui Song33204002024-09-21 18:51:021573 return [&ctx = this->ctx] {
Fangrui Songcf57a672024-09-21 18:06:061574 return alignToPowerOf2(ctx.script->getDot(), ctx.arg.maxPageSize);
Fangrui Song4629aa12024-08-22 04:23:281575 };
Rui Ueyama2ec34542017-04-05 05:07:391576 }
Rui Ueyama3837f422019-07-10 05:00:371577 if (tok == "DEFINED") {
Fangrui Song74f843d2024-07-27 23:47:171578 StringRef name = readParenName();
Fangrui Song65a15a52023-09-09 21:46:511579 // Return 1 if s is defined. If the definition is only found in a linker
1580 // script, it must happen before this DEFINED.
1581 auto order = ctx.scriptSymOrderCounter++;
Fangrui Song33204002024-09-21 18:51:021582 return [=, &ctx = this->ctx] {
Fangrui Songdf0864e2024-09-23 17:33:431583 Symbol *s = ctx.symtab->find(name);
Fangrui Song65a15a52023-09-09 21:46:511584 return s && s->isDefined() && ctx.scriptSymOrder.lookup(s) < order ? 1
1585 : 0;
Hafiz Abid Qadeer1f166ed2020-07-16 20:40:311586 };
Rui Ueyama2ec34542017-04-05 05:07:391587 }
Rui Ueyama3837f422019-07-10 05:00:371588 if (tok == "LENGTH") {
Fangrui Song74f843d2024-07-27 23:47:171589 StringRef name = readParenName();
Fangrui Song4629aa12024-08-22 04:23:281590 if (ctx.script->memoryRegions.count(name) == 0) {
Rui Ueyama3837f422019-07-10 05:00:371591 setError("memory region not defined: " + name);
George Rimarb068b032018-03-01 12:36:011592 return [] { return 0; };
1593 }
Fangrui Song4629aa12024-08-22 04:23:281594 return ctx.script->memoryRegions[name]->length;
Rui Ueyama91b95b62017-05-09 18:24:381595 }
Rui Ueyama3837f422019-07-10 05:00:371596 if (tok == "LOADADDR") {
Fangrui Song74f843d2024-07-27 23:47:171597 StringRef name = readParenName();
Fangrui Song4629aa12024-08-22 04:23:281598 OutputSection *osec = &ctx.script->getOrCreateOutputSection(name)->osec;
Fangrui Song9e9c86f2022-02-28 19:19:001599 osec->usedInExpression = true;
Fangrui Song33204002024-09-21 18:51:021600 return [=, s = ctx.script] {
1601 checkIfExists(*s, *osec, location);
Fangrui Song9e9c86f2022-02-28 19:19:001602 return osec->getLMA();
Rui Ueyama617e2f92017-10-08 02:27:021603 };
Rui Ueyama2ec34542017-04-05 05:07:391604 }
Isaac Richterfa1145a2020-07-27 08:49:241605 if (tok == "LOG2CEIL") {
1606 expect("(");
1607 Expr a = readExpr();
1608 expect(")");
1609 return [=] {
1610 // LOG2CEIL(0) is defined to be 0.
1611 return llvm::Log2_64_Ceil(std::max(a().getValue(), UINT64_C(1)));
1612 };
1613 }
Rui Ueyama3837f422019-07-10 05:00:371614 if (tok == "MAX" || tok == "MIN") {
George Rimarfd115602018-03-28 11:33:001615 expect("(");
Rui Ueyama3837f422019-07-10 05:00:371616 Expr a = readExpr();
George Rimarfd115602018-03-28 11:33:001617 expect(",");
Rui Ueyama3837f422019-07-10 05:00:371618 Expr b = readExpr();
George Rimarfd115602018-03-28 11:33:001619 expect(")");
Rui Ueyama3837f422019-07-10 05:00:371620 if (tok == "MIN")
1621 return [=] { return std::min(a().getValue(), b().getValue()); };
1622 return [=] { return std::max(a().getValue(), b().getValue()); };
George Rimarfd115602018-03-28 11:33:001623 }
Rui Ueyama3837f422019-07-10 05:00:371624 if (tok == "ORIGIN") {
Fangrui Song74f843d2024-07-27 23:47:171625 StringRef name = readParenName();
Fangrui Song4629aa12024-08-22 04:23:281626 if (ctx.script->memoryRegions.count(name) == 0) {
Rui Ueyama3837f422019-07-10 05:00:371627 setError("memory region not defined: " + name);
George Rimarb068b032018-03-01 12:36:011628 return [] { return 0; };
1629 }
Fangrui Song4629aa12024-08-22 04:23:281630 return ctx.script->memoryRegions[name]->origin;
Rui Ueyama91b95b62017-05-09 18:24:381631 }
Rui Ueyama3837f422019-07-10 05:00:371632 if (tok == "SEGMENT_START") {
Rui Ueyama2ec34542017-04-05 05:07:391633 expect("(");
1634 skip();
1635 expect(",");
Rui Ueyama3837f422019-07-10 05:00:371636 Expr e = readExpr();
Rui Ueyama2ec34542017-04-05 05:07:391637 expect(")");
Rui Ueyama3837f422019-07-10 05:00:371638 return [=] { return e(); };
Rui Ueyama2ec34542017-04-05 05:07:391639 }
Rui Ueyama3837f422019-07-10 05:00:371640 if (tok == "SIZEOF") {
Fangrui Song74f843d2024-07-27 23:47:171641 StringRef name = readParenName();
Fangrui Song4629aa12024-08-22 04:23:281642 OutputSection *cmd = &ctx.script->getOrCreateOutputSection(name)->osec;
Rafael Espindola05c4f672017-06-01 01:16:501643 // Linker script does not create an output section if its content is empty.
1644 // We want to allow SIZEOF(.foo) where .foo is a section which happened to
1645 // be empty.
Rui Ueyama3837f422019-07-10 05:00:371646 return [=] { return cmd->size; };
Rui Ueyama2ec34542017-04-05 05:07:391647 }
Rui Ueyama3837f422019-07-10 05:00:371648 if (tok == "SIZEOF_HEADERS")
Fangrui Song35900682024-10-04 03:06:581649 return [=, &ctx = ctx] { return elf::getHeaderSize(ctx); };
Rui Ueyama2ec34542017-04-05 05:07:391650
Rui Ueyama4eb2ecc2017-04-05 18:02:301651 // Tok is the dot.
Rui Ueyama3837f422019-07-10 05:00:371652 if (tok == ".")
Fangrui Song33204002024-09-21 18:51:021653 return [=, s = ctx.script] { return s->getSymbolValue(tok, location); };
Rui Ueyama4eb2ecc2017-04-05 18:02:301654
Rui Ueyama2ec34542017-04-05 05:07:391655 // Tok is a literal number.
Fangrui Song4191fda2022-11-27 03:19:151656 if (std::optional<uint64_t> val = parseInt(tok))
Rui Ueyama3837f422019-07-10 05:00:371657 return [=] { return *val; };
Rui Ueyama2ec34542017-04-05 05:07:391658
1659 // Tok is a symbol name.
Fangrui Song8d85c962023-06-05 21:36:191660 if (tok.starts_with("\""))
Fangrui Song2bf06d92021-09-27 16:50:411661 tok = unquote(tok);
1662 else if (!isValidSymbolName(tok))
Rui Ueyama3837f422019-07-10 05:00:371663 setError("malformed number: " + tok);
Parth Aroraebb326a2024-03-25 23:11:211664 if (activeProvideSym)
Fangrui Song4629aa12024-08-22 04:23:281665 ctx.script->provideMap[*activeProvideSym].push_back(tok);
Parth Aroraebb326a2024-03-25 23:11:211666 else
Fangrui Song4629aa12024-08-22 04:23:281667 ctx.script->referencedSymbols.push_back(tok);
Fangrui Song33204002024-09-21 18:51:021668 return [=, s = ctx.script] { return s->getSymbolValue(tok, location); };
Rui Ueyama2ec34542017-04-05 05:07:391669}
1670
Rui Ueyama3837f422019-07-10 05:00:371671Expr ScriptParser::readTernary(Expr cond) {
1672 Expr l = readExpr();
Rui Ueyama2ec34542017-04-05 05:07:391673 expect(":");
Rui Ueyama3837f422019-07-10 05:00:371674 Expr r = readExpr();
1675 return [=] { return cond().getValue() ? l() : r(); };
Rui Ueyama2ec34542017-04-05 05:07:391676}
1677
1678Expr ScriptParser::readParenExpr() {
1679 expect("(");
Rui Ueyama3837f422019-07-10 05:00:371680 Expr e = readExpr();
Rui Ueyama2ec34542017-04-05 05:07:391681 expect(")");
Rui Ueyama3837f422019-07-10 05:00:371682 return e;
Rui Ueyama2ec34542017-04-05 05:07:391683}
1684
Fangrui Songa1c2ee02021-12-26 21:53:471685SmallVector<StringRef, 0> ScriptParser::readOutputSectionPhdrs() {
1686 SmallVector<StringRef, 0> phdrs;
Fangrui Songed6c1062024-11-07 17:06:011687 while (!errCount(ctx) && peek().starts_with(":")) {
Rui Ueyama3837f422019-07-10 05:00:371688 StringRef tok = next();
Fangrui Songa4921f12024-07-28 00:40:511689 phdrs.push_back((tok.size() == 1) ? readName() : tok.substr(1));
Rui Ueyama2ec34542017-04-05 05:07:391690 }
Rui Ueyama3837f422019-07-10 05:00:371691 return phdrs;
Rui Ueyama2ec34542017-04-05 05:07:391692}
1693
1694// Read a program header type name. The next token must be a
1695// name of a program header type or a constant (e.g. "0x3").
1696unsigned ScriptParser::readPhdrType() {
Rui Ueyama3837f422019-07-10 05:00:371697 StringRef tok = next();
Fangrui Song4191fda2022-11-27 03:19:151698 if (std::optional<uint64_t> val = parseInt(tok))
Rui Ueyama3837f422019-07-10 05:00:371699 return *val;
Rui Ueyama2ec34542017-04-05 05:07:391700
Rui Ueyama3837f422019-07-10 05:00:371701 unsigned ret = StringSwitch<unsigned>(tok)
Rui Ueyama2ec34542017-04-05 05:07:391702 .Case("PT_NULL", PT_NULL)
1703 .Case("PT_LOAD", PT_LOAD)
1704 .Case("PT_DYNAMIC", PT_DYNAMIC)
1705 .Case("PT_INTERP", PT_INTERP)
1706 .Case("PT_NOTE", PT_NOTE)
1707 .Case("PT_SHLIB", PT_SHLIB)
1708 .Case("PT_PHDR", PT_PHDR)
1709 .Case("PT_TLS", PT_TLS)
1710 .Case("PT_GNU_EH_FRAME", PT_GNU_EH_FRAME)
1711 .Case("PT_GNU_STACK", PT_GNU_STACK)
1712 .Case("PT_GNU_RELRO", PT_GNU_RELRO)
John Ericsond7fd8b12024-07-12 18:34:171713 .Case("PT_OPENBSD_MUTABLE", PT_OPENBSD_MUTABLE)
Rui Ueyama2ec34542017-04-05 05:07:391714 .Case("PT_OPENBSD_RANDOMIZE", PT_OPENBSD_RANDOMIZE)
John Ericsond7fd8b12024-07-12 18:34:171715 .Case("PT_OPENBSD_SYSCALLS", PT_OPENBSD_SYSCALLS)
Rui Ueyama2ec34542017-04-05 05:07:391716 .Case("PT_OPENBSD_WXNEEDED", PT_OPENBSD_WXNEEDED)
1717 .Case("PT_OPENBSD_BOOTDATA", PT_OPENBSD_BOOTDATA)
1718 .Default(-1);
1719
Rui Ueyama3837f422019-07-10 05:00:371720 if (ret == (unsigned)-1) {
1721 setError("invalid program header type: " + tok);
Rui Ueyama2ec34542017-04-05 05:07:391722 return PT_NULL;
1723 }
Rui Ueyama3837f422019-07-10 05:00:371724 return ret;
Rui Ueyama2ec34542017-04-05 05:07:391725}
1726
1727// Reads an anonymous version declaration.
1728void ScriptParser::readAnonymousDeclaration() {
Fangrui Song64038ef2021-12-27 04:12:551729 SmallVector<SymbolVersion, 0> locals;
1730 SmallVector<SymbolVersion, 0> globals;
Rui Ueyama3837f422019-07-10 05:00:371731 std::tie(locals, globals) = readSymbols();
Fangrui Songe28a70d2019-08-05 14:31:391732 for (const SymbolVersion &pat : locals)
Fangrui Songcf57a672024-09-21 18:06:061733 ctx.arg.versionDefinitions[VER_NDX_LOCAL].localPatterns.push_back(pat);
Fangrui Songe28a70d2019-08-05 14:31:391734 for (const SymbolVersion &pat : globals)
Fangrui Songcf57a672024-09-21 18:06:061735 ctx.arg.versionDefinitions[VER_NDX_GLOBAL].nonLocalPatterns.push_back(pat);
Rui Ueyama2ec34542017-04-05 05:07:391736
1737 expect(";");
1738}
1739
1740// Reads a non-anonymous version definition,
1741// e.g. "VerStr { global: foo; bar; local: *; };".
Rui Ueyama3837f422019-07-10 05:00:371742void ScriptParser::readVersionDeclaration(StringRef verStr) {
Rui Ueyama2ec34542017-04-05 05:07:391743 // Read a symbol list.
Fangrui Song64038ef2021-12-27 04:12:551744 SmallVector<SymbolVersion, 0> locals;
1745 SmallVector<SymbolVersion, 0> globals;
Rui Ueyama3837f422019-07-10 05:00:371746 std::tie(locals, globals) = readSymbols();
Rui Ueyama2ec34542017-04-05 05:07:391747
1748 // Create a new version definition and add that to the global symbols.
Rui Ueyama3837f422019-07-10 05:00:371749 VersionDefinition ver;
1750 ver.name = verStr;
Fangrui Song00809c82021-08-05 06:52:551751 ver.nonLocalPatterns = std::move(globals);
1752 ver.localPatterns = std::move(locals);
Fangrui Songcf57a672024-09-21 18:06:061753 ver.id = ctx.arg.versionDefinitions.size();
1754 ctx.arg.versionDefinitions.push_back(ver);
Rui Ueyama2ec34542017-04-05 05:07:391755
1756 // Each version may have a parent version. For example, "Ver2"
1757 // defined as "Ver2 { global: foo; local: *; } Ver1;" has "Ver1"
1758 // as a parent. This version hierarchy is, probably against your
1759 // instinct, purely for hint; the runtime doesn't care about it
1760 // at all. In LLD, we simply ignore it.
Fangrui Song5f380402020-02-08 22:10:291761 if (next() != ";")
1762 expect(";");
Rui Ueyama2ec34542017-04-05 05:07:391763}
1764
Fangrui Song49279ca12020-06-18 00:11:381765bool elf::hasWildcard(StringRef s) {
Rui Ueyama3837f422019-07-10 05:00:371766 return s.find_first_of("?*[") != StringRef::npos;
Rui Ueyama1e77ad12017-07-13 20:30:351767}
1768
Rui Ueyama2ec34542017-04-05 05:07:391769// Reads a list of symbols, e.g. "{ global: foo; bar; local: *; };".
Fangrui Song64038ef2021-12-27 04:12:551770std::pair<SmallVector<SymbolVersion, 0>, SmallVector<SymbolVersion, 0>>
Rui Ueyama2ec34542017-04-05 05:07:391771ScriptParser::readSymbols() {
Fangrui Song64038ef2021-12-27 04:12:551772 SmallVector<SymbolVersion, 0> locals;
1773 SmallVector<SymbolVersion, 0> globals;
1774 SmallVector<SymbolVersion, 0> *v = &globals;
Rui Ueyama2ec34542017-04-05 05:07:391775
Hongyu Chenf1a7d142024-07-27 21:16:121776 while (auto tok = till("}")) {
1777 if (tok == "extern") {
Fangrui Song64038ef2021-12-27 04:12:551778 SmallVector<SymbolVersion, 0> ext = readVersionExtern();
Rui Ueyama3837f422019-07-10 05:00:371779 v->insert(v->end(), ext.begin(), ext.end());
Rui Ueyama2ec34542017-04-05 05:07:391780 } else {
Hongyu Chen2ae862b2024-07-24 05:03:461781 if (tok == "local:" || (tok == "local" && consume(":"))) {
1782 v = &locals;
1783 continue;
1784 }
1785 if (tok == "global:" || (tok == "global" && consume(":"))) {
1786 v = &globals;
1787 continue;
1788 }
Rui Ueyama3837f422019-07-10 05:00:371789 v->push_back({unquote(tok), false, hasWildcard(tok)});
Rui Ueyama2ec34542017-04-05 05:07:391790 }
1791 expect(";");
1792 }
Rui Ueyama3837f422019-07-10 05:00:371793 return {locals, globals};
Rui Ueyama2ec34542017-04-05 05:07:391794}
1795
1796// Reads an "extern C++" directive, e.g.,
1797// "extern "C++" { ns::*; "f(int, double)"; };"
Rui Ueyama17324d82018-02-01 23:46:171798//
1799// The last semicolon is optional. E.g. this is OK:
1800// "extern "C++" { ns::*; "f(int, double)" };"
Fangrui Song64038ef2021-12-27 04:12:551801SmallVector<SymbolVersion, 0> ScriptParser::readVersionExtern() {
Rui Ueyama3837f422019-07-10 05:00:371802 StringRef tok = next();
1803 bool isCXX = tok == "\"C++\"";
1804 if (!isCXX && tok != "\"C\"")
Rui Ueyama2ec34542017-04-05 05:07:391805 setError("Unknown language");
1806 expect("{");
1807
Fangrui Song64038ef2021-12-27 04:12:551808 SmallVector<SymbolVersion, 0> ret;
Fangrui Songb32c38a2024-07-27 00:25:231809 while (auto tok = till("}")) {
Rui Ueyama3837f422019-07-10 05:00:371810 ret.push_back(
Fangrui Songb32c38a2024-07-27 00:25:231811 {unquote(tok), isCXX, !tok.str.starts_with("\"") && hasWildcard(tok)});
Rui Ueyama17324d82018-02-01 23:46:171812 if (consume("}"))
Rui Ueyama3837f422019-07-10 05:00:371813 return ret;
Rui Ueyama2ec34542017-04-05 05:07:391814 expect(";");
1815 }
Rui Ueyama3837f422019-07-10 05:00:371816 return ret;
Rui Ueyama2ec34542017-04-05 05:07:391817}
1818
Fangrui Song92b5b982020-03-06 19:49:581819Expr ScriptParser::readMemoryAssignment(StringRef s1, StringRef s2,
1820 StringRef s3) {
Rui Ueyama3837f422019-07-10 05:00:371821 if (!consume(s1) && !consume(s2) && !consume(s3)) {
1822 setError("expected one of: " + s1 + ", " + s2 + ", or " + s3);
Fangrui Song92b5b982020-03-06 19:49:581823 return [] { return 0; };
Rui Ueyama2ec34542017-04-05 05:07:391824 }
1825 expect("=");
Fangrui Song92b5b982020-03-06 19:49:581826 return readExpr();
Rui Ueyama2ec34542017-04-05 05:07:391827}
1828
1829// Parse the MEMORY command as specified in:
1830// https://sourceware.org/binutils/docs/ld/MEMORY.html
1831//
1832// MEMORY { name [(attr)] : ORIGIN = origin, LENGTH = len ... }
1833void ScriptParser::readMemory() {
1834 expect("{");
Fangrui Song2a893562024-07-27 00:13:371835 while (auto tok = till("}")) {
Rui Ueyama3837f422019-07-10 05:00:371836 if (tok == "INCLUDE") {
Rui Ueyama2e9d40d2018-10-12 17:07:321837 readInclude();
1838 continue;
1839 }
Rui Ueyama2ec34542017-04-05 05:07:391840
Rui Ueyama3837f422019-07-10 05:00:371841 uint32_t flags = 0;
Igor Kudrin8cdf1c12021-11-24 05:17:031842 uint32_t invFlags = 0;
Rui Ueyama3837f422019-07-10 05:00:371843 uint32_t negFlags = 0;
Igor Kudrin8cdf1c12021-11-24 05:17:031844 uint32_t negInvFlags = 0;
Rui Ueyama2ec34542017-04-05 05:07:391845 if (consume("(")) {
Igor Kudrin8cdf1c12021-11-24 05:17:031846 readMemoryAttributes(flags, invFlags, negFlags, negInvFlags);
Rui Ueyama2ec34542017-04-05 05:07:391847 expect(")");
1848 }
1849 expect(":");
1850
Fangrui Song92b5b982020-03-06 19:49:581851 Expr origin = readMemoryAssignment("ORIGIN", "org", "o");
Rui Ueyama2ec34542017-04-05 05:07:391852 expect(",");
Fangrui Song92b5b982020-03-06 19:49:581853 Expr length = readMemoryAssignment("LENGTH", "len", "l");
Rui Ueyama2ec34542017-04-05 05:07:391854
George Rimar5f375412017-09-08 08:23:151855 // Add the memory region to the region map.
Igor Kudrin8cdf1c12021-11-24 05:17:031856 MemoryRegion *mr = make<MemoryRegion>(tok, origin, length, flags, invFlags,
1857 negFlags, negInvFlags);
Fangrui Song4629aa12024-08-22 04:23:281858 if (!ctx.script->memoryRegions.insert({tok, mr}).second)
Rui Ueyama3837f422019-07-10 05:00:371859 setError("region '" + tok + "' already defined");
Rui Ueyama2ec34542017-04-05 05:07:391860 }
1861}
1862
1863// This function parses the attributes used to match against section
1864// flags when placing output sections in a memory region. These flags
1865// are only used when an explicit memory region name is not used.
Igor Kudrin8cdf1c12021-11-24 05:17:031866void ScriptParser::readMemoryAttributes(uint32_t &flags, uint32_t &invFlags,
1867 uint32_t &negFlags,
1868 uint32_t &negInvFlags) {
Rui Ueyama3837f422019-07-10 05:00:371869 bool invert = false;
Rui Ueyama2ec34542017-04-05 05:07:391870
Rui Ueyama3837f422019-07-10 05:00:371871 for (char c : next().lower()) {
Igor Kudrin8cdf1c12021-11-24 05:17:031872 if (c == '!') {
Rui Ueyama3837f422019-07-10 05:00:371873 invert = !invert;
Igor Kudrin8cdf1c12021-11-24 05:17:031874 std::swap(flags, negFlags);
1875 std::swap(invFlags, negInvFlags);
1876 continue;
1877 }
1878 if (c == 'w')
1879 flags |= SHF_WRITE;
Rui Ueyama3837f422019-07-10 05:00:371880 else if (c == 'x')
Igor Kudrin8cdf1c12021-11-24 05:17:031881 flags |= SHF_EXECINSTR;
Rui Ueyama3837f422019-07-10 05:00:371882 else if (c == 'a')
Igor Kudrin8cdf1c12021-11-24 05:17:031883 flags |= SHF_ALLOC;
1884 else if (c == 'r')
1885 invFlags |= SHF_WRITE;
Rui Ueyama2ec34542017-04-05 05:07:391886 else
Igor Kudrin8cdf1c12021-11-24 05:17:031887 setError("invalid memory region attribute");
Rui Ueyama2ec34542017-04-05 05:07:391888 }
Igor Kudrin8cdf1c12021-11-24 05:17:031889
1890 if (invert) {
1891 std::swap(flags, negFlags);
1892 std::swap(invFlags, negInvFlags);
1893 }
Rui Ueyama2ec34542017-04-05 05:07:391894}
1895
Fangrui Songcf57a672024-09-21 18:06:061896void elf::readLinkerScript(Ctx &ctx, MemoryBufferRef mb) {
James Henderson439341b2020-11-03 14:41:091897 llvm::TimeTraceScope timeScope("Read linker script",
1898 mb.getBufferIdentifier());
Fangrui Songcf57a672024-09-21 18:06:061899 ScriptParser(ctx, mb).readLinkerScript();
Rui Ueyama2ec34542017-04-05 05:07:391900}
1901
Fangrui Songcf57a672024-09-21 18:06:061902void elf::readVersionScript(Ctx &ctx, MemoryBufferRef mb) {
James Henderson439341b2020-11-03 14:41:091903 llvm::TimeTraceScope timeScope("Read version script",
1904 mb.getBufferIdentifier());
Fangrui Songcf57a672024-09-21 18:06:061905 ScriptParser(ctx, mb).readVersionScript();
Rui Ueyama2ec34542017-04-05 05:07:391906}
1907
Fangrui Songcf57a672024-09-21 18:06:061908void elf::readDynamicList(Ctx &ctx, MemoryBufferRef mb) {
James Henderson439341b2020-11-03 14:41:091909 llvm::TimeTraceScope timeScope("Read dynamic list", mb.getBufferIdentifier());
Fangrui Songcf57a672024-09-21 18:06:061910 ScriptParser(ctx, mb).readDynamicList();
Petr Hosek8c7e8cc2017-11-04 02:03:581911}
Fangrui Songbd8cfe62019-10-07 08:31:181912
Fangrui Songcf57a672024-09-21 18:06:061913void elf::readDefsym(Ctx &ctx, MemoryBufferRef mb) {
1914 ScriptParser(ctx, mb).readDefsym();
1915}