summaryrefslogtreecommitdiff
path: root/lib/ReaderWriter/LinkerScript.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ReaderWriter/LinkerScript.cpp')
-rw-r--r--lib/ReaderWriter/LinkerScript.cpp411
1 files changed, 371 insertions, 40 deletions
diff --git a/lib/ReaderWriter/LinkerScript.cpp b/lib/ReaderWriter/LinkerScript.cpp
index 56194cae5e724..67822dc48fe60 100644
--- a/lib/ReaderWriter/LinkerScript.cpp
+++ b/lib/ReaderWriter/LinkerScript.cpp
@@ -1,4 +1,4 @@
-//===- ReaderWriter/LinkerScript.cpp --------------------------------------===//
+//===- ReaderWriter/LinkerScript.cpp ----------------------------*- C++ -*-===//
//
// The LLVM Linker
//
@@ -14,6 +14,11 @@
#include "lld/ReaderWriter/LinkerScript.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/ELF.h"
+
namespace lld {
namespace script {
void Token::dump(raw_ostream &os) const {
@@ -63,6 +68,9 @@ void Token::dump(raw_ostream &os) const {
CASE(kw_entry)
CASE(kw_exclude_file)
CASE(kw_extern)
+ CASE(kw_filehdr)
+ CASE(kw_fill)
+ CASE(kw_flags)
CASE(kw_group)
CASE(kw_hidden)
CASE(kw_input)
@@ -70,6 +78,7 @@ void Token::dump(raw_ostream &os) const {
CASE(kw_length)
CASE(kw_memory)
CASE(kw_origin)
+ CASE(kw_phdrs)
CASE(kw_provide)
CASE(kw_provide_hidden)
CASE(kw_only_if_ro)
@@ -100,7 +109,7 @@ static llvm::ErrorOr<uint64_t> parseDecimal(StringRef str) {
for (auto &c : str) {
res *= 10;
if (c < '0' || c > '9')
- return llvm::ErrorOr<uint64_t>(std::make_error_code(std::errc::io_error));
+ return llvm::ErrorOr<uint64_t>(make_error_code(llvm::errc::io_error));
res += c - '0';
}
return res;
@@ -111,7 +120,7 @@ static llvm::ErrorOr<uint64_t> parseOctal(StringRef str) {
for (auto &c : str) {
res <<= 3;
if (c < '0' || c > '7')
- return llvm::ErrorOr<uint64_t>(std::make_error_code(std::errc::io_error));
+ return llvm::ErrorOr<uint64_t>(make_error_code(llvm::errc::io_error));
res += c - '0';
}
return res;
@@ -122,7 +131,7 @@ static llvm::ErrorOr<uint64_t> parseBinary(StringRef str) {
for (auto &c : str) {
res <<= 1;
if (c != '0' && c != '1')
- return llvm::ErrorOr<uint64_t>(std::make_error_code(std::errc::io_error));
+ return llvm::ErrorOr<uint64_t>(make_error_code(llvm::errc::io_error));
res += c - '0';
}
return res;
@@ -139,7 +148,7 @@ static llvm::ErrorOr<uint64_t> parseHex(StringRef str) {
else if (c >= 'A' && c <= 'F')
res += c - 'A' + 10;
else
- return llvm::ErrorOr<uint64_t>(std::make_error_code(std::errc::io_error));
+ return llvm::ErrorOr<uint64_t>(make_error_code(llvm::errc::io_error));
}
return res;
}
@@ -469,6 +478,9 @@ void Lexer::lex(Token &tok) {
.Case("ENTRY", Token::kw_entry)
.Case("EXCLUDE_FILE", Token::kw_exclude_file)
.Case("EXTERN", Token::kw_extern)
+ .Case("FILEHDR", Token::kw_filehdr)
+ .Case("FILL", Token::kw_fill)
+ .Case("FLAGS", Token::kw_flags)
.Case("GROUP", Token::kw_group)
.Case("HIDDEN", Token::kw_hidden)
.Case("INPUT", Token::kw_input)
@@ -486,6 +498,7 @@ void Lexer::lex(Token &tok) {
.Case("OUTPUT_ARCH", Token::kw_output_arch)
.Case("OUTPUT_FORMAT", Token::kw_output_format)
.Case("OVERLAY", Token::kw_overlay)
+ .Case("PHDRS", Token::kw_phdrs)
.Case("PROVIDE", Token::kw_provide)
.Case("PROVIDE_HIDDEN", Token::kw_provide_hidden)
.Case("SEARCH_DIR", Token::kw_search_dir)
@@ -544,14 +557,14 @@ void Lexer::skipWhitespace() {
// Constant functions
void Constant::dump(raw_ostream &os) const { os << _num; }
-ErrorOr<int64_t> Constant::evalExpr(SymbolTableTy &symbolTable) const {
+ErrorOr<int64_t> Constant::evalExpr(const SymbolTableTy &symbolTable) const {
return _num;
}
// Symbol functions
void Symbol::dump(raw_ostream &os) const { os << _name; }
-ErrorOr<int64_t> Symbol::evalExpr(SymbolTableTy &symbolTable) const {
+ErrorOr<int64_t> Symbol::evalExpr(const SymbolTableTy &symbolTable) const {
auto it = symbolTable.find(_name);
if (it == symbolTable.end())
return LinkerScriptReaderError::unknown_symbol_in_expr;
@@ -569,7 +582,8 @@ void FunctionCall::dump(raw_ostream &os) const {
os << ")";
}
-ErrorOr<int64_t> FunctionCall::evalExpr(SymbolTableTy &symbolTable) const {
+ErrorOr<int64_t>
+FunctionCall::evalExpr(const SymbolTableTy &symbolTable) const {
return LinkerScriptReaderError::unrecognized_function_in_expr;
}
@@ -584,7 +598,7 @@ void Unary::dump(raw_ostream &os) const {
os << ")";
}
-ErrorOr<int64_t> Unary::evalExpr(SymbolTableTy &symbolTable) const {
+ErrorOr<int64_t> Unary::evalExpr(const SymbolTableTy &symbolTable) const {
auto child = _child->evalExpr(symbolTable);
if (child.getError())
return child.getError();
@@ -654,7 +668,7 @@ void BinOp::dump(raw_ostream &os) const {
os << ")";
}
-ErrorOr<int64_t> BinOp::evalExpr(SymbolTableTy &symbolTable) const {
+ErrorOr<int64_t> BinOp::evalExpr(const SymbolTableTy &symbolTable) const {
auto lhs = _lhs->evalExpr(symbolTable);
if (lhs.getError())
return lhs.getError();
@@ -695,7 +709,7 @@ void TernaryConditional::dump(raw_ostream &os) const {
}
ErrorOr<int64_t>
-TernaryConditional::evalExpr(SymbolTableTy &symbolTable) const {
+TernaryConditional::evalExpr(const SymbolTableTy &symbolTable) const {
auto conditional = _conditional->evalExpr(symbolTable);
if (conditional.getError())
return conditional.getError();
@@ -857,6 +871,12 @@ void InputSectionsCmd::dump(raw_ostream &os) const {
os << ")";
}
+void FillCmd::dump(raw_ostream &os) const {
+ os << "FILL(";
+ dumpByteStream(os, StringRef((const char *)_bytes.begin(), _bytes.size()));
+ os << ")";
+}
+
// OutputSectionDescription functions
void OutputSectionDescription::dump(raw_ostream &os) const {
if (_discard)
@@ -909,6 +929,9 @@ void OutputSectionDescription::dump(raw_ostream &os) const {
}
os << " }";
+ for (auto && phdr : _phdrs)
+ os << " : " << phdr;
+
if (_fillStream.size() > 0) {
os << " =";
dumpByteStream(os, _fillStream);
@@ -918,6 +941,37 @@ void OutputSectionDescription::dump(raw_ostream &os) const {
}
}
+// Special header that discards output sections assigned to it.
+static const PHDR PHDR_NONE("NONE", 0, false, false, nullptr, 0);
+
+bool PHDR::isNone() const {
+ return this == &PHDR_NONE;
+}
+
+void PHDR::dump(raw_ostream &os) const {
+ os << _name << " " << _type;
+ if (_includeFileHdr)
+ os << " FILEHDR";
+ if (_includePHDRs)
+ os << " PHDRS";
+ if (_at) {
+ os << " AT (";
+ _at->dump(os);
+ os << ")";
+ }
+ if (_flags)
+ os << " FLAGS (" << _flags << ")";
+ os << ";\n";
+}
+
+void PHDRS::dump(raw_ostream &os) const {
+ os << "PHDRS\n{\n";
+ for (auto &&phdr : _phdrs) {
+ phdr->dump(os);
+ }
+ os << "}\n";
+}
+
// Sections functions
void Sections::dump(raw_ostream &os) const {
os << "SECTIONS\n{\n";
@@ -965,7 +1019,6 @@ void Extern::dump(raw_ostream &os) const {
os << ")\n";
}
-
// Parser functions
std::error_code Parser::parse() {
// Get the first token.
@@ -1024,6 +1077,13 @@ std::error_code Parser::parse() {
_script._commands.push_back(entry);
break;
}
+ case Token::kw_phdrs: {
+ PHDRS *phdrs = parsePHDRS();
+ if (!phdrs)
+ return LinkerScriptReaderError::parse_error;
+ _script._commands.push_back(phdrs);
+ break;
+ }
case Token::kw_search_dir: {
SearchDir *searchDir = parseSearchDir();
if (!searchDir)
@@ -1122,7 +1182,7 @@ const Expression *Parser::parseExprOperand() {
case Token::identifier: {
if (peek()._kind== Token::l_paren)
return parseFunctionCall();
- Symbol *sym = new (_alloc) Symbol(*this, _tok._range);
+ auto *sym = new (_alloc) Symbol(*this, _tok._range);
consumeToken();
return sym;
}
@@ -1140,7 +1200,7 @@ const Expression *Parser::parseExprOperand() {
error(_tok, "Unrecognized number constant");
return nullptr;
}
- Constant *c = new (_alloc) Constant(*this, *val);
+ auto *c = new (_alloc) Constant(*this, *val);
consumeToken();
return c;
}
@@ -1588,7 +1648,7 @@ llvm::ErrorOr<InputSectionsCmd::VectorTy> Parser::parseExcludeFile() {
if (!expectAndConsume(Token::l_paren, "expected ("))
return llvm::ErrorOr<InputSectionsCmd::VectorTy>(
- std::make_error_code(std::errc::io_error));
+ make_error_code(llvm::errc::io_error));
while (_tok._kind == Token::identifier) {
res.push_back(new (_alloc) InputSectionName(*this, _tok._range, true));
@@ -1597,7 +1657,7 @@ llvm::ErrorOr<InputSectionsCmd::VectorTy> Parser::parseExcludeFile() {
if (!expectAndConsume(Token::r_paren, "expected )"))
return llvm::ErrorOr<InputSectionsCmd::VectorTy>(
- std::make_error_code(std::errc::io_error));
+ make_error_code(llvm::errc::io_error));
return llvm::ErrorOr<InputSectionsCmd::VectorTy>(std::move(res));
}
@@ -1793,6 +1853,46 @@ const InputSectionsCmd *Parser::parseInputSectionsCmd() {
archiveSortMode, inputSections);
}
+const FillCmd *Parser::parseFillCmd() {
+ assert(_tok._kind == Token::kw_fill && "Expected FILL!");
+ consumeToken();
+ if (!expectAndConsume(Token::l_paren, "expected ("))
+ return nullptr;
+
+ SmallVector<uint8_t, 8> storage;
+
+ // If the expression is just a number, it's arbitrary length.
+ if (_tok._kind == Token::number && peek()._kind == Token::r_paren) {
+ if (_tok._range.size() > 2 && _tok._range.startswith("0x")) {
+ StringRef num = _tok._range.substr(2);
+ for (char c : num) {
+ unsigned nibble = llvm::hexDigitValue(c);
+ if (nibble == -1u)
+ goto not_simple_hex;
+ storage.push_back(nibble);
+ }
+
+ if (storage.size() % 2 != 0)
+ storage.insert(storage.begin(), 0);
+
+ // Collapse nibbles.
+ for (std::size_t i = 0, e = storage.size() / 2; i != e; ++i)
+ storage[i] = (storage[i * 2] << 4) + storage[(i * 2) + 1];
+
+ storage.resize(storage.size() / 2);
+ }
+ }
+not_simple_hex:
+
+ const Expression *expr = parseExpression();
+ if (!expr)
+ return nullptr;
+ if (!expectAndConsume(Token::r_paren, "expected )"))
+ return nullptr;
+
+ return new(getAllocator()) FillCmd(*this, storage);
+}
+
const OutputSectionDescription *Parser::parseOutputSectionDescription() {
assert((_tok._kind == Token::kw_discard || _tok._kind == Token::identifier) &&
"Expected /DISCARD/ or identifier!");
@@ -1892,6 +1992,12 @@ const OutputSectionDescription *Parser::parseOutputSectionDescription() {
break;
}
break;
+ case Token::kw_fill:
+ if (const Command *cmd = parseFillCmd())
+ outputSectionCommands.push_back(cmd);
+ else
+ return nullptr;
+ break;
case Token::kw_keep:
case Token::star:
case Token::colon:
@@ -1921,6 +2027,17 @@ const OutputSectionDescription *Parser::parseOutputSectionDescription() {
if (!expectAndConsume(Token::r_brace, "expected }"))
return nullptr;
+ SmallVector<StringRef, 2> phdrs;
+ while (_tok._kind == Token::colon) {
+ consumeToken();
+ if (_tok._kind != Token::identifier) {
+ error(_tok, "expected program header name");
+ return nullptr;
+ }
+ phdrs.push_back(_tok._range);
+ consumeToken();
+ }
+
if (_tok._kind == Token::equal) {
consumeToken();
if (_tok._kind != Token::number || !_tok._range.startswith_lower("0x")) {
@@ -1945,7 +2062,7 @@ const OutputSectionDescription *Parser::parseOutputSectionDescription() {
return new (_alloc) OutputSectionDescription(
*this, sectionName, address, align, subAlign, at, fillExpr, fillStream,
- alignWithInput, discard, constraint, outputSectionCommands);
+ alignWithInput, discard, constraint, outputSectionCommands, phdrs);
}
const Overlay *Parser::parseOverlay() {
@@ -1954,6 +2071,141 @@ const Overlay *Parser::parseOverlay() {
return nullptr;
}
+const PHDR *Parser::parsePHDR() {
+ assert(_tok._kind == Token::identifier && "Expected identifier!");
+
+ StringRef name = _tok._range;
+ consumeToken();
+
+ uint64_t type;
+
+ switch (_tok._kind) {
+ case Token::identifier:
+ case Token::number:
+ case Token::l_paren: {
+ const Expression *expr = parseExpression();
+ if (!expr)
+ return nullptr;
+ Expression::SymbolTableTy PHDRTypes;
+#define PHDR_INSERT(x) PHDRTypes.insert(std::make_pair(#x, llvm::ELF::x))
+ PHDR_INSERT(PT_NULL);
+ PHDR_INSERT(PT_LOAD);
+ PHDR_INSERT(PT_DYNAMIC);
+ PHDR_INSERT(PT_INTERP);
+ PHDR_INSERT(PT_NOTE);
+ PHDR_INSERT(PT_SHLIB);
+ PHDR_INSERT(PT_PHDR);
+ PHDR_INSERT(PT_TLS);
+ PHDR_INSERT(PT_LOOS);
+ PHDR_INSERT(PT_GNU_EH_FRAME);
+ PHDR_INSERT(PT_GNU_STACK);
+ PHDR_INSERT(PT_GNU_RELRO);
+ PHDR_INSERT(PT_SUNW_EH_FRAME);
+ PHDR_INSERT(PT_SUNW_UNWIND);
+ PHDR_INSERT(PT_HIOS);
+ PHDR_INSERT(PT_LOPROC);
+ PHDR_INSERT(PT_ARM_ARCHEXT);
+ PHDR_INSERT(PT_ARM_EXIDX);
+ PHDR_INSERT(PT_ARM_UNWIND);
+ PHDR_INSERT(PT_MIPS_REGINFO);
+ PHDR_INSERT(PT_MIPS_RTPROC);
+ PHDR_INSERT(PT_MIPS_OPTIONS);
+ PHDR_INSERT(PT_MIPS_ABIFLAGS);
+ PHDR_INSERT(PT_HIPROC);
+#undef PHDR_INSERT
+ auto t = expr->evalExpr(PHDRTypes);
+ if (t == LinkerScriptReaderError::unknown_symbol_in_expr) {
+ error(_tok, "Unknown type");
+ return nullptr;
+ }
+ if (!t)
+ return nullptr;
+ type = *t;
+ break;
+ }
+ default:
+ error(_tok, "expected identifier or expression");
+ return nullptr;
+ }
+
+ uint64_t flags = 0;
+ const Expression *flagsExpr = nullptr;
+ bool includeFileHdr = false;
+ bool includePHDRs = false;
+
+ while (_tok._kind != Token::semicolon) {
+ switch (_tok._kind) {
+ case Token::kw_filehdr:
+ if (includeFileHdr) {
+ error(_tok, "Duplicate FILEHDR attribute");
+ return nullptr;
+ }
+ includeFileHdr = true;
+ consumeToken();
+ break;
+ case Token::kw_phdrs:
+ if (includePHDRs) {
+ error(_tok, "Duplicate PHDRS attribute");
+ return nullptr;
+ }
+ includePHDRs = true;
+ consumeToken();
+ break;
+ case Token::kw_flags: {
+ if (flagsExpr) {
+ error(_tok, "Duplicate FLAGS attribute");
+ return nullptr;
+ }
+ consumeToken();
+ if (!expectAndConsume(Token::l_paren, "Expected ("))
+ return nullptr;
+ flagsExpr = parseExpression();
+ if (!flagsExpr)
+ return nullptr;
+ auto f = flagsExpr->evalExpr();
+ if (!f)
+ return nullptr;
+ flags = *f;
+ if (!expectAndConsume(Token::r_paren, "Expected )"))
+ return nullptr;
+ } break;
+ default:
+ error(_tok, "Unexpected token");
+ return nullptr;
+ }
+ }
+
+ if (!expectAndConsume(Token::semicolon, "Expected ;"))
+ return nullptr;
+
+ return new (getAllocator())
+ PHDR(name, type, includeFileHdr, includePHDRs, nullptr, flags);
+}
+
+PHDRS *Parser::parsePHDRS() {
+ assert(_tok._kind == Token::kw_phdrs && "Expected PHDRS!");
+ consumeToken();
+ if (!expectAndConsume(Token::l_brace, "expected {"))
+ return nullptr;
+
+ SmallVector<const PHDR *, 8> phdrs;
+
+ while (true) {
+ if (_tok._kind == Token::identifier) {
+ const PHDR *phdr = parsePHDR();
+ if (!phdr)
+ return nullptr;
+ phdrs.push_back(phdr);
+ } else
+ break;
+ }
+
+ if (!expectAndConsume(Token::r_brace, "expected }"))
+ return nullptr;
+
+ return new (getAllocator()) PHDRS(*this, phdrs);
+}
+
Sections *Parser::parseSections() {
assert(_tok._kind == Token::kw_sections && "Expected SECTIONS!");
consumeToken();
@@ -2101,8 +2353,7 @@ Memory *Parser::parseMemory() {
if (!length)
return nullptr;
- MemoryBlock *block =
- new (_alloc) MemoryBlock(name, attrs, origin, length);
+ auto *block = new (_alloc) MemoryBlock(name, attrs, origin, length);
blocks.push_back(block);
} else {
unrecognizedToken = true;
@@ -2142,14 +2393,22 @@ Extern *Parser::parseExtern() {
}
// Sema member functions
-Sema::Sema()
- : _scripts(), _layoutCommands(), _memberToLayoutOrder(),
- _memberNameWildcards(), _cacheSectionOrder(), _cacheExpressionOrder(),
- _deliveredExprs(), _symbolTable() {}
+Sema::Sema() : _programPHDR(nullptr) {}
+
+std::error_code Sema::perform() {
+ llvm::StringMap<const PHDR *> phdrs;
-void Sema::perform() {
- for (auto &parser : _scripts)
- perform(parser->get());
+ for (auto &parser : _scripts) {
+ for (const Command *c : parser->get()->_commands) {
+ if (const auto *sec = dyn_cast<Sections>(c)) {
+ linearizeAST(sec);
+ } else if (const auto *ph = dyn_cast<PHDRS>(c)) {
+ if (auto ec = collectPHDRs(ph, phdrs))
+ return ec;
+ }
+ }
+ }
+ return buildSectionToPHDR(phdrs);
}
bool Sema::less(const SectionKey &lhs, const SectionKey &rhs) const {
@@ -2254,6 +2513,15 @@ uint64_t Sema::getLinkerScriptExprValue(StringRef name) const {
return it->second;
}
+bool Sema::hasPHDRs() const { return !_sectionToPHDR.empty(); }
+
+std::vector<const PHDR *> Sema::getPHDRsForOutputSection(StringRef name) const {
+ auto vec = _sectionToPHDR.lookup(name);
+ return std::vector<const PHDR *>(std::begin(vec), std::end(vec));
+}
+
+const PHDR *Sema::getProgramPHDR() const { return _programPHDR; }
+
void Sema::dump() const {
raw_ostream &os = llvm::outs();
os << "Linker script semantics dump\n";
@@ -2287,7 +2555,7 @@ static bool wildcardMatch(StringRef pattern, StringRef name) {
switch (*j) {
case '*':
while (!wildcardMatch(pattern.drop_front(j - pattern.begin() + 1),
- name.drop_front(i - name.begin() + 1))) {
+ name.drop_front(i - name.begin()))) {
if (i == name.end())
return false;
++i;
@@ -2295,6 +2563,7 @@ static bool wildcardMatch(StringRef pattern, StringRef name) {
break;
case '?':
// Matches any character
+ ++i;
break;
case '[': {
// Matches a range of characters specified between brackets
@@ -2307,20 +2576,22 @@ static bool wildcardMatch(StringRef pattern, StringRef name) {
return false;
j = pattern.begin() + end;
+ ++i;
break;
}
case '\\':
++j;
if (*j != *i)
return false;
+ ++i;
break;
default:
// No wildcard character means we must match exactly the same char
if (*j != *i)
return false;
+ ++i;
break;
}
- ++i;
}
// If our pattern has't consumed the entire string, it is not a match
@@ -2376,11 +2647,10 @@ int Sema::getLayoutOrder(const SectionKey &key, bool coarse) const {
// If we still couldn't find a rule for this input section, try to match
// wildcards
- for (auto I = _memberNameWildcards.begin(), E = _memberNameWildcards.end();
- I != E; ++I) {
- if (!wildcardMatch(I->first, key.memberPath))
+ for (const auto &I : _memberNameWildcards) {
+ if (!wildcardMatch(I.first, key.memberPath))
continue;
- int order = I->second;
+ int order = I.second;
int exprOrder = -1;
if ((exprOrder = matchSectionName(order, key)) >= 0) {
@@ -2490,6 +2760,74 @@ bool Sema::localCompare(int order, const SectionKey &lhs,
return false;
}
+std::error_code Sema::collectPHDRs(const PHDRS *ph,
+ llvm::StringMap<const PHDR *> &phdrs) {
+ bool loadFound = false;
+ for (auto *p : *ph) {
+ phdrs[p->name()] = p;
+
+ switch (p->type()) {
+ case llvm::ELF::PT_PHDR:
+ if (_programPHDR != nullptr)
+ return LinkerScriptReaderError::extra_program_phdr;
+ if (loadFound)
+ return LinkerScriptReaderError::misplaced_program_phdr;
+ if (!p->hasPHDRs())
+ return LinkerScriptReaderError::program_phdr_wrong_phdrs;
+ _programPHDR = p;
+ break;
+ case llvm::ELF::PT_LOAD:
+ // Program header, if available, should have program header table
+ // mapped in the first loadable segment.
+ if (!loadFound && _programPHDR && !p->hasPHDRs())
+ return LinkerScriptReaderError::program_phdr_wrong_phdrs;
+ loadFound = true;
+ break;
+ }
+ }
+ return std::error_code();
+}
+
+std::error_code Sema::buildSectionToPHDR(llvm::StringMap<const PHDR *> &phdrs) {
+ const bool noPhdrs = phdrs.empty();
+
+ // Add NONE header to the map provided there's no user-defined
+ // header with the same name.
+ if (!phdrs.count(PHDR_NONE.name()))
+ phdrs[PHDR_NONE.name()] = &PHDR_NONE;
+
+ // Match output sections to available headers.
+ llvm::SmallVector<const PHDR *, 2> phdrsCur, phdrsLast { &PHDR_NONE };
+ for (const Command *cmd : _layoutCommands) {
+ auto osd = dyn_cast<OutputSectionDescription>(cmd);
+ if (!osd || osd->isDiscarded())
+ continue;
+
+ phdrsCur.clear();
+ for (StringRef name : osd->PHDRs()) {
+ auto it = phdrs.find(name);
+ if (it == phdrs.end()) {
+ return LinkerScriptReaderError::unknown_phdr_ids;
+ }
+ phdrsCur.push_back(it->second);
+ }
+
+ // If no headers and no errors - insert empty headers set.
+ // If the current set of headers is empty, then use the last non-empty
+ // set. Otherwise mark the current set to be the last non-empty set for
+ // successors.
+ if (noPhdrs)
+ phdrsCur.clear();
+ else if (phdrsCur.empty())
+ phdrsCur = phdrsLast;
+ else
+ phdrsLast = phdrsCur;
+
+ _sectionToPHDR[osd->name()] = phdrsCur;
+ }
+ return std::error_code();
+}
+
static bool hasWildcard(StringRef name) {
for (auto ch : name)
if (ch == '*' || ch == '?' || ch == '[' || ch == '\\')
@@ -2553,12 +2891,5 @@ void Sema::linearizeAST(const Sections *sections) {
}
}
-void Sema::perform(const LinkerScript *ls) {
- for (const Command *c : ls->_commands) {
- if (const Sections *sec = dyn_cast<Sections>(c))
- linearizeAST(sec);
- }
-}
-
-} // End namespace script
+} // end namespace script
} // end namespace lld