[lld] r238383 - Add PHDR and FILL parsing.

Michael J. Spencer bigcheesegs at gmail.com
Wed May 27 17:14:59 PDT 2015


Author: mspencer
Date: Wed May 27 19:14:58 2015
New Revision: 238383

URL: http://llvm.org/viewvc/llvm-project?rev=238383&view=rev
Log:
Add PHDR and FILL parsing.

Added:
    lld/trunk/test/LinkerScript/phdrs-sections.test
Modified:
    lld/trunk/include/lld/ReaderWriter/LinkerScript.h
    lld/trunk/lib/ReaderWriter/LinkerScript.cpp
    lld/trunk/test/LinkerScript/sections.test

Modified: lld/trunk/include/lld/ReaderWriter/LinkerScript.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/LinkerScript.h?rev=238383&r1=238382&r2=238383&view=diff
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/LinkerScript.h (original)
+++ lld/trunk/include/lld/ReaderWriter/LinkerScript.h Wed May 27 19:14:58 2015
@@ -78,6 +78,7 @@ public:
     kw_entry,
     kw_exclude_file,
     kw_extern,
+    kw_fill,
     kw_group,
     kw_hidden,
     kw_input,
@@ -85,6 +86,7 @@ public:
     kw_length,
     kw_memory,
     kw_origin,
+    kw_phdrs,
     kw_provide,
     kw_provide_hidden,
     kw_only_if_ro,
@@ -160,6 +162,7 @@ public:
   enum class Kind {
     Entry,
     Extern,
+    Fill,
     Group,
     Input,
     InputSectionsCmd,
@@ -170,6 +173,7 @@ public:
     OutputFormat,
     OutputSectionDescription,
     Overlay,
+    PHDRS,
     SearchDir,
     Sections,
     SortedGroup,
@@ -191,6 +195,14 @@ private:
   Kind _kind;
 };
 
+template <class T>
+ArrayRef<T> save_array(llvm::BumpPtrAllocator &alloc, ArrayRef<T> array) {
+  size_t num = array.size();
+  T *start = alloc.Allocate<T>(num);
+  std::uninitialized_copy(std::begin(array), std::end(array), start);
+  return llvm::makeArrayRef(start, num);
+}
+
 class Output : public Command {
 public:
   Output(Parser &ctx, StringRef outputFileName)
@@ -212,10 +224,7 @@ class OutputFormat : public Command {
 public:
   OutputFormat(Parser &ctx, const SmallVectorImpl<StringRef> &formats)
       : Command(ctx, Kind::OutputFormat) {
-    size_t numFormats = formats.size();
-    StringRef *formatsStart = getAllocator().Allocate<StringRef>(numFormats);
-    std::copy(std::begin(formats), std::end(formats), formatsStart);
-    _formats = llvm::makeArrayRef(formatsStart, numFormats);
+    _formats = save_array<StringRef>(getAllocator(), formats);
   }
 
   static bool classof(const Command *c) {
@@ -274,10 +283,7 @@ class PathList : public Command {
 public:
   PathList(Parser &ctx, StringRef name, const SmallVectorImpl<Path> &paths)
       : Command(ctx, K), _name(name) {
-    size_t numPaths = paths.size();
-    Path *pathsStart = getAllocator().template Allocate<Path>(numPaths);
-    std::copy(std::begin(paths), std::end(paths), pathsStart);
-    _paths = llvm::makeArrayRef(pathsStart, numPaths);
+    _paths = save_array<Path>(getAllocator(), paths);
   }
 
   static bool classof(const Command *c) { return c->getKind() == K; }
@@ -382,7 +388,8 @@ public:
   Kind getKind() const { return _kind; }
   inline llvm::BumpPtrAllocator &getAllocator() const;
   virtual void dump(raw_ostream &os) const = 0;
-  virtual ErrorOr<int64_t> evalExpr(SymbolTableTy &symbolTable) const = 0;
+  virtual ErrorOr<int64_t>
+  evalExpr(const SymbolTableTy &symbolTable = SymbolTableTy()) const = 0;
   virtual ~Expression() {}
 
 protected:
@@ -406,7 +413,7 @@ public:
     return c->getKind() == Kind::Constant;
   }
 
-  ErrorOr<int64_t> evalExpr(SymbolTableTy &symbolTable) const override;
+  ErrorOr<int64_t> evalExpr(const SymbolTableTy &symbolTable) const override;
 
 private:
   uint64_t _num;
@@ -422,7 +429,7 @@ public:
     return c->getKind() == Kind::Symbol;
   }
 
-  ErrorOr<int64_t> evalExpr(SymbolTableTy &symbolTable) const override;
+  ErrorOr<int64_t> evalExpr(const SymbolTableTy &symbolTable) const override;
 
 private:
   StringRef _name;
@@ -433,11 +440,7 @@ public:
   FunctionCall(Parser &ctx, StringRef name,
                const SmallVectorImpl<const Expression *> &args)
       : Expression(ctx, Kind::FunctionCall), _name(name) {
-    size_t numArgs = args.size();
-    const Expression **argsStart =
-        getAllocator().Allocate<const Expression *>(numArgs);
-    std::copy(std::begin(args), std::end(args), argsStart);
-    _args = llvm::makeArrayRef(argsStart, numArgs);
+    _args = save_array<const Expression *>(getAllocator(), args);
   }
 
   void dump(raw_ostream &os) const override;
@@ -446,7 +449,7 @@ public:
     return c->getKind() == Kind::FunctionCall;
   }
 
-  ErrorOr<int64_t> evalExpr(SymbolTableTy &symbolTable) const override;
+  ErrorOr<int64_t> evalExpr(const SymbolTableTy &symbolTable) const override;
 
 private:
   StringRef _name;
@@ -468,7 +471,7 @@ public:
     return c->getKind() == Kind::Unary;
   }
 
-  ErrorOr<int64_t> evalExpr(SymbolTableTy &symbolTable) const override;
+  ErrorOr<int64_t> evalExpr(const SymbolTableTy &symbolTable) const override;
 
 private:
   Operation _op;
@@ -503,7 +506,7 @@ public:
     return c->getKind() == Kind::BinOp;
   }
 
-  ErrorOr<int64_t> evalExpr(SymbolTableTy &symbolTable) const override;
+  ErrorOr<int64_t> evalExpr(const SymbolTableTy &symbolTable) const override;
 
 private:
   Operation _op;
@@ -538,7 +541,7 @@ public:
     return c->getKind() == Kind::TernaryConditional;
   }
 
-  ErrorOr<int64_t> evalExpr(SymbolTableTy &symbolTable) const override;
+  ErrorOr<int64_t> evalExpr(const SymbolTableTy &symbolTable) const override;
 
 private:
   const Expression *_conditional;
@@ -647,11 +650,7 @@ public:
   InputSectionSortedGroup(Parser &ctx, WildcardSortMode sort,
                           const SmallVectorImpl<const InputSection *> &sections)
       : InputSection(ctx, Kind::SortedGroup), _sortMode(sort) {
-    size_t numSections = sections.size();
-    const InputSection **sectionsStart =
-        getAllocator().Allocate<const InputSection *>(numSections);
-    std::copy(std::begin(sections), std::end(sections), sectionsStart);
-    _sections = llvm::makeArrayRef(sectionsStart, numSections);
+    _sections = save_array<const InputSection *>(getAllocator(), sections);
   }
 
   void dump(raw_ostream &os) const override;
@@ -691,11 +690,7 @@ public:
       : Command(ctx, Kind::InputSectionsCmd), _memberName(memberName),
         _archiveName(archiveName), _keep(keep), _fileSortMode(fileSortMode),
         _archiveSortMode(archiveSortMode) {
-    size_t numSections = sections.size();
-    const InputSection **sectionsStart =
-        getAllocator().Allocate<const InputSection *>(numSections);
-    std::copy(std::begin(sections), std::end(sections), sectionsStart);
-    _sections = llvm::makeArrayRef(sectionsStart, numSections);
+    _sections = save_array<const InputSection *>(getAllocator(), sections);
   }
 
   void dump(raw_ostream &os) const override;
@@ -720,6 +715,24 @@ private:
   llvm::ArrayRef<const InputSection *> _sections;
 };
 
+class FillCmd : public Command {
+public:
+  FillCmd(Parser &ctx, ArrayRef<uint8_t> bytes) : Command(ctx, Kind::Fill) {
+    _bytes = save_array<uint8_t>(getAllocator(), bytes);
+  }
+
+  void dump(raw_ostream &os) const override;
+
+  static bool classof(const Command *c) {
+    return c->getKind() == Kind::Fill;
+  }
+
+  ArrayRef<uint8_t> bytes() { return _bytes; }
+
+private:
+  ArrayRef<uint8_t> _bytes;
+};
+
 /// A sections-command to specify which input sections and symbols compose a
 /// given output section.
 /// Example:
@@ -743,18 +756,16 @@ public:
       const Expression *align, const Expression *subAlign, const Expression *at,
       const Expression *fillExpr, StringRef fillStream, bool alignWithInput,
       bool discard, Constraint constraint,
-      const SmallVectorImpl<const Command *> &outputSectionCommands)
+      const SmallVectorImpl<const Command *> &outputSectionCommands,
+      ArrayRef<StringRef> phdrs)
       : Command(ctx, Kind::OutputSectionDescription), _sectionName(sectionName),
         _address(address), _align(align), _subAlign(subAlign), _at(at),
         _fillExpr(fillExpr), _fillStream(fillStream),
         _alignWithInput(alignWithInput), _discard(discard),
         _constraint(constraint) {
-    size_t numCommands = outputSectionCommands.size();
-    const Command **commandsStart =
-        getAllocator().Allocate<const Command *>(numCommands);
-    std::copy(std::begin(outputSectionCommands),
-              std::end(outputSectionCommands), commandsStart);
-    _outputSectionCommands = llvm::makeArrayRef(commandsStart, numCommands);
+    _outputSectionCommands =
+        save_array<const Command *>(getAllocator(), outputSectionCommands);
+    _phdrs = save_array<StringRef>(getAllocator(), phdrs);
   }
 
   static bool classof(const Command *c) {
@@ -779,6 +790,7 @@ private:
   bool _discard;
   Constraint _constraint;
   llvm::ArrayRef<const Command *> _outputSectionCommands;
+  ArrayRef<StringRef> _phdrs;
 };
 
 /// Represents an Overlay structure as documented in
@@ -794,6 +806,47 @@ public:
   void dump(raw_ostream &os) const override { os << "Overlay description\n"; }
 };
 
+class PHDR {
+public:
+  PHDR(StringRef name, uint64_t type, bool includeFileHdr, bool includePHDRs,
+       const Expression *at, uint64_t flags)
+      : _name(name), _type(type), _includeFileHdr(includeFileHdr),
+        _includePHDRs(includePHDRs), _at(at), _flags(flags) {}
+
+  ~PHDR() = delete;
+
+  void dump(raw_ostream &os) const;
+
+private:
+  StringRef _name;
+  uint64_t _type;
+  bool _includeFileHdr;
+  bool _includePHDRs;
+  const Expression *_at;
+  uint64_t _flags;
+};
+
+class PHDRS : public Command {
+public:
+  typedef ArrayRef<const PHDR *>::const_iterator const_iterator;
+
+  PHDRS(Parser &ctx, const SmallVectorImpl<const PHDR *> &phdrs)
+      : Command(ctx, Kind::PHDRS) {
+    _phdrs = save_array<const PHDR *>(getAllocator(), phdrs);
+  }
+
+  static bool classof(const Command *c) {
+    return c->getKind() == Kind::PHDRS;
+  }
+
+  void dump(raw_ostream &os) const override;
+  const_iterator begin() const { return _phdrs.begin(); }
+  const_iterator end() const { return _phdrs.end(); }
+
+private:
+  ArrayRef<const PHDR *> _phdrs;
+};
+
 /// Represents all the contents of the SECTIONS {} construct.
 class Sections : public Command {
 public:
@@ -802,12 +855,8 @@ public:
   Sections(Parser &ctx,
            const SmallVectorImpl<const Command *> &sectionsCommands)
       : Command(ctx, Kind::Sections) {
-    size_t numCommands = sectionsCommands.size();
-    const Command **commandsStart =
-        getAllocator().Allocate<const Command *>(numCommands);
-    std::copy(std::begin(sectionsCommands), std::end(sectionsCommands),
-              commandsStart);
-    _sectionsCommands = llvm::makeArrayRef(commandsStart, numCommands);
+    _sectionsCommands =
+        save_array<const Command *>(getAllocator(), sectionsCommands);
   }
 
   static bool classof(const Command *c) {
@@ -844,11 +893,7 @@ public:
   Memory(Parser &ctx,
          const SmallVectorImpl<const MemoryBlock *> &blocks)
       : Command(ctx, Kind::Memory) {
-    size_t numBlocks = blocks.size();
-    const MemoryBlock **blocksStart =
-        getAllocator().Allocate<const MemoryBlock *>(numBlocks);
-    std::copy(std::begin(blocks), std::end(blocks), blocksStart);
-    _blocks = llvm::makeArrayRef(blocksStart, numBlocks);
+    _blocks = save_array<const MemoryBlock *>(getAllocator(), blocks);
   }
 
   static bool classof(const Command *c) {
@@ -869,11 +914,7 @@ public:
   Extern(Parser &ctx,
          const SmallVectorImpl<StringRef> &symbols)
       : Command(ctx, Kind::Extern) {
-    size_t numSymbols = symbols.size();
-    StringRef *symbolsStart =
-        getAllocator().Allocate<StringRef>(numSymbols);
-    std::copy(std::begin(symbols), std::end(symbols), symbolsStart);
-    _symbols = llvm::makeArrayRef(symbolsStart, numSymbols);
+    _symbols = save_array<StringRef>(getAllocator(), symbols);
   }
 
   static bool classof(const Command *c) {
@@ -1133,6 +1174,8 @@ private:
   /// }
   const InputSectionsCmd *parseInputSectionsCmd();
 
+  const FillCmd *parseFillCmd();
+
   /// Parse output section description statements.
   /// Example:
   ///
@@ -1145,6 +1188,10 @@ private:
   /// Stub for parsing overlay commands. Currently unimplemented.
   const Overlay *parseOverlay();
 
+  const PHDR *parsePHDR();
+
+  PHDRS *parsePHDRS();
+
   /// Parse the SECTIONS linker script command.
   /// Example:
   ///

Modified: lld/trunk/lib/ReaderWriter/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/LinkerScript.cpp?rev=238383&r1=238382&r2=238383&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/LinkerScript.cpp (original)
+++ lld/trunk/lib/ReaderWriter/LinkerScript.cpp Wed May 27 19:14:58 2015
@@ -14,6 +14,10 @@
 
 #include "lld/ReaderWriter/LinkerScript.h"
 
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/ELF.h"
+
 namespace lld {
 namespace script {
 void Token::dump(raw_ostream &os) const {
@@ -63,6 +67,7 @@ void Token::dump(raw_ostream &os) const
     CASE(kw_entry)
     CASE(kw_exclude_file)
     CASE(kw_extern)
+    CASE(kw_fill)
     CASE(kw_group)
     CASE(kw_hidden)
     CASE(kw_input)
@@ -70,6 +75,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)
@@ -469,6 +475,7 @@ void Lexer::lex(Token &tok) {
             .Case("ENTRY", Token::kw_entry)
             .Case("EXCLUDE_FILE", Token::kw_exclude_file)
             .Case("EXTERN", Token::kw_extern)
+            .Case("FILL", Token::kw_fill)
             .Case("GROUP", Token::kw_group)
             .Case("HIDDEN", Token::kw_hidden)
             .Case("INPUT", Token::kw_input)
@@ -486,6 +493,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 +552,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 +577,8 @@ void FunctionCall::dump(raw_ostream &os)
   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 +593,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 +663,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 +704,7 @@ void TernaryConditional::dump(raw_ostrea
 }
 
 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 +866,12 @@ void InputSectionsCmd::dump(raw_ostream
     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 +924,9 @@ void OutputSectionDescription::dump(raw_
   }
   os << "  }";
 
+  for (auto && phdr : _phdrs)
+    os << " : " << phdr;
+
   if (_fillStream.size() > 0) {
     os << " =";
     dumpByteStream(os, _fillStream);
@@ -918,6 +936,21 @@ void OutputSectionDescription::dump(raw_
   }
 }
 
+void PHDR::dump(raw_ostream &os) const {
+  os << _name << " " << _type;
+  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";
@@ -1024,6 +1057,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)
@@ -1793,6 +1833,46 @@ const InputSectionsCmd *Parser::parseInp
                        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 +1972,12 @@ const OutputSectionDescription *Parser::
         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 +2007,17 @@ const OutputSectionDescription *Parser::
   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 +2042,7 @@ const OutputSectionDescription *Parser::
 
   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 +2051,110 @@ 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;
+
+  if (_tok._kind == Token::identifier && _tok._range == "FLAGS") {
+    consumeToken();
+    if (!expectAndConsume(Token::l_paren, "Expected ("))
+      return nullptr;
+    const Expression *flagsExpr = parseExpression();
+    if (!flagsExpr)
+      return nullptr;
+    auto f = flagsExpr->evalExpr();
+    if (!f)
+      return nullptr;
+    flags = *f;
+    if (!expectAndConsume(Token::r_paren, "Expected )"))
+      return nullptr;
+  }
+  
+  if (!expectAndConsume(Token::semicolon, "Expected ;"))
+    return nullptr;
+
+  return new (getAllocator()) PHDR(name, type, false, false, 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();

Added: lld/trunk/test/LinkerScript/phdrs-sections.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/LinkerScript/phdrs-sections.test?rev=238383&view=auto
==============================================================================
--- lld/trunk/test/LinkerScript/phdrs-sections.test (added)
+++ lld/trunk/test/LinkerScript/phdrs-sections.test Wed May 27 19:14:58 2015
@@ -0,0 +1,29 @@
+/*
+  Test PHDR parsing and section -> phdr mapping.
+  RUN: linker-script-test %s | FileCheck %s
+*/
+
+PHDRS
+{
+  ph_text PT_LOAD FLAGS (0x1 | 0x4);
+  ph_data PT_LOAD FLAGS (0x2 | 0x4);
+}
+
+SECTIONS 
+{
+  .init : {} : ph_text
+}
+
+/*
+CHECK: PHDRS
+CHECK: {
+CHECK: ph_text 1 FLAGS (5);
+CHECK: ph_data 1 FLAGS (6);
+CHECK: }
+CHECK: SECTIONS
+CHECK: {
+CHECK: .init :
+CHECK:   {
+CHECK:   } : ph_text
+CHECK: }
+*/

Modified: lld/trunk/test/LinkerScript/sections.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/LinkerScript/sections.test?rev=238383&r1=238382&r2=238383&view=diff
==============================================================================
--- lld/trunk/test/LinkerScript/sections.test (original)
+++ lld/trunk/test/LinkerScript/sections.test Wed May 27 19:14:58 2015
@@ -26,6 +26,7 @@ SECTIONS
     }
   .init           :
   {
+    FILL (0x90909090)
     KEEP (*(SORT_NONE(.init)))
   } =0x909090909090909090909090
   PROVIDE (__etext = .);
@@ -181,6 +182,10 @@ CHECK: r_brace: }
 CHECK: identifier: .init
 CHECK: colon: :
 CHECK: l_brace: {
+CHECK: kw_fill: FILL
+CHECK: l_paren: (
+CHECK: number: 0x90909090
+CHECK: r_paren: )
 CHECK: kw_keep: KEEP
 CHECK: l_paren: (
 CHECK: star: *
@@ -556,6 +561,7 @@ CHECK:     PROVIDE_HIDDEN(__rela_iplt_en
 CHECK:   }
 CHECK: .init :
 CHECK:   {
+CHECK:     FILL(0x90909090)
 CHECK:     KEEP(*(SORT_NONE(.init)))
 CHECK:   } =0x909090909090909090909090
 CHECK: PROVIDE(__etext = .)





More information about the llvm-commits mailing list