diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2015-12-30 11:57:38 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2015-12-30 11:57:38 +0000 | 
| commit | 5a5c549fe9a3fef595297bd21d36bed8409dc37d (patch) | |
| tree | a964c8f5ac85b7b641cac022c5f9bf4eed3d2b9b /lib/ReaderWriter/LinkerScript.cpp | |
| parent | fb911942f1434f3d1750f83f25f5e42c80e60638 (diff) | |
Notes
Diffstat (limited to 'lib/ReaderWriter/LinkerScript.cpp')
| -rw-r--r-- | lib/ReaderWriter/LinkerScript.cpp | 411 | 
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 | 
