[lld] r244743 - [LinkerScript] Process program header in PHDRS command

Denis Protivensky via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 12 05:31:36 PDT 2015


Author: denis-protivensky
Date: Wed Aug 12 07:31:35 2015
New Revision: 244743

URL: http://llvm.org/viewvc/llvm-project?rev=244743&view=rev
Log:
[LinkerScript] Process program header in PHDRS command

Add PT_PHDR segment depending on its availability in linker script's
PHDRS command, fallback if no linker script is given.
Handle FILEHDR, PHDRS and FLAGS attributes of program header.

Differential Revision: http://reviews.llvm.org/D11589

Added:
    lld/trunk/test/elf/linkerscript/phdrs-extra-program.test
    lld/trunk/test/elf/linkerscript/phdrs-has-program.test
    lld/trunk/test/elf/linkerscript/phdrs-misplaced-program.test
    lld/trunk/test/elf/linkerscript/phdrs-no-program.test
    lld/trunk/test/elf/linkerscript/phdrs-program-flags.test
    lld/trunk/test/elf/linkerscript/phdrs-program-good-phdrs.test
    lld/trunk/test/elf/linkerscript/phdrs-program-no-phdrs.test
    lld/trunk/test/elf/linkerscript/phdrs-program-wrong-phdrs.test
Modified:
    lld/trunk/include/lld/Core/Error.h
    lld/trunk/include/lld/ReaderWriter/LinkerScript.h
    lld/trunk/lib/Core/Error.cpp
    lld/trunk/lib/Driver/GnuLdDriver.cpp
    lld/trunk/lib/ReaderWriter/ELF/SegmentChunks.cpp
    lld/trunk/lib/ReaderWriter/ELF/TargetLayout.cpp
    lld/trunk/lib/ReaderWriter/LinkerScript.cpp
    lld/trunk/test/elf/linkerscript/phdrs-invalid.test

Modified: lld/trunk/include/lld/Core/Error.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/Error.h?rev=244743&r1=244742&r2=244743&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/Error.h (original)
+++ lld/trunk/include/lld/Core/Error.h Wed Aug 12 07:31:35 2015
@@ -38,6 +38,9 @@ enum class LinkerScriptReaderError {
   unknown_symbol_in_expr,
   unrecognized_function_in_expr,
   unknown_phdr_ids,
+  extra_program_phdr,
+  misplaced_program_phdr,
+  program_phdr_wrong_phdrs,
 };
 
 inline std::error_code make_error_code(LinkerScriptReaderError e) {

Modified: lld/trunk/include/lld/ReaderWriter/LinkerScript.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/LinkerScript.h?rev=244743&r1=244742&r2=244743&view=diff
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/LinkerScript.h (original)
+++ lld/trunk/include/lld/ReaderWriter/LinkerScript.h Wed Aug 12 07:31:35 2015
@@ -79,7 +79,9 @@ public:
     kw_entry,
     kw_exclude_file,
     kw_extern,
+    kw_filehdr,
     kw_fill,
+    kw_flags,
     kw_group,
     kw_hidden,
     kw_input,
@@ -818,6 +820,8 @@ public:
 
   StringRef name() const { return _name; }
   uint64_t type() const { return _type; }
+  bool hasFileHdr() const { return _includeFileHdr; }
+  bool hasPHDRs() const { return _includePHDRs; }
   uint64_t flags() const { return _flags; }
   bool isNone() const;
 
@@ -1284,7 +1288,7 @@ public:
   /// Prepare our data structures according to the linker scripts currently in
   /// our control (control given via addLinkerScript()). Called once all linker
   /// scripts have been parsed.
-  void perform();
+  std::error_code perform();
 
   /// Answer if we have layout commands (section mapping rules). If we don't,
   /// the output file writer can assume there is no linker script special rule
@@ -1326,12 +1330,14 @@ public:
   /// has been performed (by calling evalExpr() for all expressions).
   uint64_t getLinkerScriptExprValue(StringRef name) const;
 
+  /// Check if there are custom headers available.
+  bool hasPHDRs() const;
+
   /// Retrieve all the headers the given output section is assigned to.
-  /// Error is returned if the output section is assigned to headers with
-  /// missing declarations.
-  std::error_code
-  getPHDRsForOutputSection(StringRef name,
-                           std::vector<const PHDR *> &phdrs) const;
+  std::vector<const PHDR *> getPHDRsForOutputSection(StringRef name) const;
+
+  /// Retrieve program header if available.
+  const PHDR *getProgramPHDR() const;
 
   void dump() const;
 
@@ -1374,9 +1380,14 @@ private:
   bool localCompare(int order, const SectionKey &lhs,
                     const SectionKey &rhs) const;
 
+  /// Convert the PHDRS command into map of names to headers.
+  /// Determine program header during processing.
+  std::error_code collectPHDRs(const PHDRS *ph,
+                               llvm::StringMap<const PHDR *> &phdrs);
+
   /// Build map that matches output section names to segments they should be
   /// put into.
-  std::error_code buildSectionToPHDR();
+  std::error_code buildSectionToPHDR(llvm::StringMap<const PHDR *> &phdrs);
 
   /// Our goal with all linearizeAST overloaded functions is to
   /// traverse the linker script AST while putting nodes in a vector and
@@ -1433,8 +1444,6 @@ private:
   void linearizeAST(const InputSectionsCmd *inputSections);
   void linearizeAST(const InputSection *inputSection);
 
-  void perform(const LinkerScript *ls);
-
   std::vector<std::unique_ptr<Parser>> _scripts;
   std::vector<const Command *> _layoutCommands;
   std::unordered_multimap<std::string, int> _memberToLayoutOrder;
@@ -1444,8 +1453,8 @@ private:
   llvm::DenseSet<int> _deliveredExprs;
   mutable llvm::StringSet<> _definedSymbols;
 
-  bool _parsedPHDRS;
   llvm::StringMap<llvm::SmallVector<const PHDR *, 2>> _sectionToPHDR;
+  const PHDR *_programPHDR;
 
   Expression::SymbolTableTy _symbolTable;
 };

Modified: lld/trunk/lib/Core/Error.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/Error.cpp?rev=244743&r1=244742&r2=244743&view=diff
==============================================================================
--- lld/trunk/lib/Core/Error.cpp (original)
+++ lld/trunk/lib/Core/Error.cpp Wed Aug 12 07:31:35 2015
@@ -58,6 +58,12 @@ public:
              "expression";
     case LinkerScriptReaderError::unknown_phdr_ids:
       return "Unknown header identifiers (missing in PHDRS command) are used";
+    case LinkerScriptReaderError::extra_program_phdr:
+      return "Extra program header is found";
+    case LinkerScriptReaderError::misplaced_program_phdr:
+      return "Program header must precede load segments";
+    case LinkerScriptReaderError::program_phdr_wrong_phdrs:
+      return "Program header has invalid PHDRS attribute";
     }
     llvm_unreachable("An enumerator of LinkerScriptReaderError does not have a "
                      "message defined.");

Modified: lld/trunk/lib/Driver/GnuLdDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/GnuLdDriver.cpp?rev=244743&r1=244742&r2=244743&view=diff
==============================================================================
--- lld/trunk/lib/Driver/GnuLdDriver.cpp (original)
+++ lld/trunk/lib/Driver/GnuLdDriver.cpp Wed Aug 12 07:31:35 2015
@@ -748,7 +748,10 @@ bool GnuLdDriver::parse(llvm::ArrayRef<c
     return false;
 
   // Perform linker script semantic actions
-  ctx->linkerScriptSema().perform();
+  if (auto ec = ctx->linkerScriptSema().perform()) {
+    diag << "Error in the linker script's semantics: " << ec.message() << "\n";
+    return false;
+  }
 
   context.swap(ctx);
   return true;

Modified: lld/trunk/lib/ReaderWriter/ELF/SegmentChunks.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/SegmentChunks.cpp?rev=244743&r1=244742&r2=244743&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/SegmentChunks.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/SegmentChunks.cpp Wed Aug 12 07:31:35 2015
@@ -423,7 +423,7 @@ template <class ELFT> int64_t Segment<EL
 }
 
 template <class ELFT> void Segment<ELFT>::setSegmentFlags(uint64_t flags) {
-  assert(!_segmentFlags && !_flags && "Flags has already been set");
+  assert(!_segmentFlags && "Segment flags have already been set");
   _segmentFlags = true;
   _flags = flags;
   _atomflags = toAtomPermsSegment(flags);

Modified: lld/trunk/lib/ReaderWriter/ELF/TargetLayout.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/TargetLayout.cpp?rev=244743&r1=244742&r2=244743&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/TargetLayout.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/TargetLayout.cpp Wed Aug 12 07:31:35 2015
@@ -330,12 +330,7 @@ template <class ELFT> void TargetLayout<
 template <class ELFT>
 std::vector<const script::PHDR *>
 TargetLayout<ELFT>::getCustomSegments(const OutputSection<ELFT> *sec) const {
-  std::vector<const script::PHDR *> phdrs;
-  if (_linkerScriptSema.getPHDRsForOutputSection(sec->name(), phdrs)) {
-    llvm::report_fatal_error(
-        "Linker script has wrong segments set for output sections");
-  }
-  return phdrs;
+  return _linkerScriptSema.getPHDRsForOutputSection(sec->name());
 }
 
 template <class ELFT>
@@ -466,11 +461,36 @@ template <class ELFT> void TargetLayout<
       }
     }
   }
-  if (_ctx.isDynamic() && !_ctx.isDynamicLibrary()) {
+
+  // Default values if no linker script is available
+  bool hasProgramSegment = _ctx.isDynamic() && !_ctx.isDynamicLibrary();
+  bool hasElfHeader = true;
+  bool hasProgramHeader = true;
+  uint64_t segmentFlags = 0;
+
+  // Check if linker script has PHDRS and program segment defined
+  if (_linkerScriptSema.hasPHDRs()) {
+    if (auto p = _linkerScriptSema.getProgramPHDR()) {
+      hasProgramSegment = true;
+      hasElfHeader = p->hasFileHdr();
+      hasProgramHeader = p->hasPHDRs();
+      segmentFlags = p->flags();
+    } else {
+      hasProgramSegment = false;
+      hasElfHeader = false;
+      hasProgramHeader = false;
+    }
+  }
+
+  if (hasProgramSegment) {
     Segment<ELFT> *segment = new (_allocator) ProgramHeaderSegment<ELFT>(_ctx);
     _segments.push_back(segment);
-    segment->append(_elfHeader);
-    segment->append(_programHeader);
+    if (segmentFlags)
+      segment->setSegmentFlags(segmentFlags);
+    if (hasElfHeader)
+      segment->append(_elfHeader);
+    if (hasProgramHeader)
+      segment->append(_programHeader);
   }
 }
 

Modified: lld/trunk/lib/ReaderWriter/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/LinkerScript.cpp?rev=244743&r1=244742&r2=244743&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/LinkerScript.cpp (original)
+++ lld/trunk/lib/ReaderWriter/LinkerScript.cpp Wed Aug 12 07:31:35 2015
@@ -68,7 +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)
@@ -476,7 +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)
@@ -2126,26 +2130,57 @@ const PHDR *Parser::parsePHDR() {
   }
 
   uint64_t flags = 0;
+  const Expression *flagsExpr = nullptr;
+  bool includeFileHdr = false;
+  bool includePHDRs = false;
 
-  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 )"))
+  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, false, false, nullptr, flags);
+  return new (getAllocator())
+      PHDR(name, type, includeFileHdr, includePHDRs, nullptr, flags);
 }
 
 PHDRS *Parser::parsePHDRS() {
@@ -2360,11 +2395,22 @@ Extern *Parser::parseExtern() {
 }
 
 // Sema member functions
-Sema::Sema() : _parsedPHDRS(false) {}
+Sema::Sema() : _programPHDR(nullptr) {}
 
-void Sema::perform() {
-  for (auto &parser : _scripts)
-    perform(parser->get());
+std::error_code Sema::perform() {
+  llvm::StringMap<const PHDR *> phdrs;
+
+  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 {
@@ -2469,18 +2515,15 @@ uint64_t Sema::getLinkerScriptExprValue(
   return it->second;
 }
 
-std::error_code
-Sema::getPHDRsForOutputSection(StringRef name,
-                               std::vector<const PHDR *> &phdrs) const {
-  // Cache results if not done yet.
-  if (auto ec = const_cast<Sema *>(this)->buildSectionToPHDR())
-    return ec;
+bool Sema::hasPHDRs() const { return !_sectionToPHDR.empty(); }
 
+std::vector<const PHDR *> Sema::getPHDRsForOutputSection(StringRef name) const {
   auto vec = _sectionToPHDR.lookup(name);
-  std::copy(std::begin(vec), std::end(vec), std::back_inserter(phdrs));
-  return std::error_code();
+  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";
@@ -2717,25 +2760,35 @@ bool Sema::localCompare(int order, const
   return false;
 }
 
-std::error_code Sema::buildSectionToPHDR() {
-  if (_parsedPHDRS)
-    return std::error_code();
-  _parsedPHDRS = true;
-
-  // No scripts - nothing to do.
-  if (_scripts.empty() || _layoutCommands.empty())
-    return std::error_code();
-
-  // Collect all header declarations.
-  llvm::StringMap<const PHDR *> phdrs;
-  for (auto &parser : _scripts) {
-    for (auto *cmd : parser->get()->_commands) {
-      if (auto *ph = dyn_cast<PHDRS>(cmd)) {
-        for (auto *p : *ph)
-          phdrs[p->name()] = p;
-      }
+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
@@ -2838,12 +2891,5 @@ void Sema::linearizeAST(const 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 lld

Added: lld/trunk/test/elf/linkerscript/phdrs-extra-program.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/linkerscript/phdrs-extra-program.test?rev=244743&view=auto
==============================================================================
--- lld/trunk/test/elf/linkerscript/phdrs-extra-program.test (added)
+++ lld/trunk/test/elf/linkerscript/phdrs-extra-program.test Wed Aug 12 07:31:35 2015
@@ -0,0 +1,27 @@
+/*
+Test extra program header generates error.
+
+RUN: yaml2obj -format=elf %p/Inputs/simple.o.yaml -o=%t.o
+
+RUN: not lld -flavor gnu -target x86_64 -T %s %t.o -static -o %t1 &> %t1-error
+RUN: FileCheck -check-prefix EXTRA-PROGRAM-PHDR %s < %t1-error
+*/
+
+ENTRY(_start)
+
+PHDRS
+{
+    header PT_PHDR PHDRS;
+    header2 PT_PHDR PHDRS;
+    text PT_LOAD;
+}
+
+SECTIONS
+{
+  .text : { *(.text) } :NONE
+  .data : { *(.data) }
+}
+
+/*
+EXTRA-PROGRAM-PHDR: Extra program header is found
+*/

Added: lld/trunk/test/elf/linkerscript/phdrs-has-program.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/linkerscript/phdrs-has-program.test?rev=244743&view=auto
==============================================================================
--- lld/trunk/test/elf/linkerscript/phdrs-has-program.test (added)
+++ lld/trunk/test/elf/linkerscript/phdrs-has-program.test Wed Aug 12 07:31:35 2015
@@ -0,0 +1,33 @@
+/*
+Test when program segment is set it's generated.
+
+RUN: yaml2obj -format=elf %p/Inputs/simple.o.yaml -o=%t.o
+
+RUN: lld -flavor gnu -target x86_64 -T %s %t.o -static -o %t1
+RUN: llvm-readobj -program-headers %t1 | FileCheck -check-prefix PROGRAM-PHDR %s
+*/
+
+ENTRY(_start)
+
+PHDRS
+{
+    header PT_PHDR FILEHDR PHDRS;
+    text PT_LOAD PHDRS;
+}
+
+SECTIONS
+{
+  .text : { *(.text) } :text
+  .data : { *(.data) }
+}
+
+/*
+PROGRAM-PHDR: ProgramHeader {
+PROGRAM-PHDR: Type: PT_PHDR (0x6)
+PROGRAM-PHDR: VirtualAddress: 0x400040
+PROGRAM-PHDR: Flags [ (0x5)
+PROGRAM-PHDR: PF_R (0x4)
+PROGRAM-PHDR: PF_X (0x1)
+PROGRAM-PHDR: ]
+PROGRAM-PHDR: }
+*/

Modified: lld/trunk/test/elf/linkerscript/phdrs-invalid.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/linkerscript/phdrs-invalid.test?rev=244743&r1=244742&r2=244743&view=diff
==============================================================================
--- lld/trunk/test/elf/linkerscript/phdrs-invalid.test (original)
+++ lld/trunk/test/elf/linkerscript/phdrs-invalid.test Wed Aug 12 07:31:35 2015
@@ -41,7 +41,7 @@ Test undefined header used when no PHDRS
 RUN: not lld -flavor gnu -target x86_64 -T %p/phdrs/undef-no-phdrs.script %t.o -static -o %t1 &> %t1-error
 RUN: FileCheck -check-prefix UNDEF-NO-PHDRS %s < %t1-error
 
-UNDEF-NO-PHDRS: Linker script has wrong segments set for output sections
+UNDEF-NO-PHDRS: Unknown header identifiers (missing in PHDRS command) are used
 */
 
 /*
@@ -50,7 +50,7 @@ Test undefined header used when PHDRS is
 RUN: not lld -flavor gnu -target x86_64 -T %p/phdrs/undef-empty-phdrs.script %t.o -static -o %t2 &> %t2-error
 RUN: FileCheck -check-prefix UNDEF-EMPTY-PHDRS %s < %t2-error
 
-UNDEF-EMPTY-PHDRS: Linker script has wrong segments set for output sections
+UNDEF-EMPTY-PHDRS: Unknown header identifiers (missing in PHDRS command) are used
 */
 
 /*
@@ -59,5 +59,5 @@ Test undefined header used when PHDRS co
 RUN: not lld -flavor gnu -target x86_64 -T %p/phdrs/undef-id-phdrs.script %t.o -static -o %t3 &> %t3-error
 RUN: FileCheck -check-prefix UNDEF-ID-PHDRS %s < %t3-error
 
-UNDEF-ID-PHDRS: Linker script has wrong segments set for output sections
+UNDEF-ID-PHDRS: Unknown header identifiers (missing in PHDRS command) are used
 */

Added: lld/trunk/test/elf/linkerscript/phdrs-misplaced-program.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/linkerscript/phdrs-misplaced-program.test?rev=244743&view=auto
==============================================================================
--- lld/trunk/test/elf/linkerscript/phdrs-misplaced-program.test (added)
+++ lld/trunk/test/elf/linkerscript/phdrs-misplaced-program.test Wed Aug 12 07:31:35 2015
@@ -0,0 +1,26 @@
+/*
+Test misplaced program header generates error.
+
+RUN: yaml2obj -format=elf %p/Inputs/simple.o.yaml -o=%t.o
+
+RUN: not lld -flavor gnu -target x86_64 -T %s %t.o -static -o %t1 &> %t1-error
+RUN: FileCheck -check-prefix MISPLACED-PROGRAM-PHDR %s < %t1-error
+*/
+
+ENTRY(_start)
+
+PHDRS
+{
+    text PT_LOAD;
+    header PT_PHDR PHDRS;
+}
+
+SECTIONS
+{
+  .text : { *(.text) } :NONE
+  .data : { *(.data) }
+}
+
+/*
+MISPLACED-PROGRAM-PHDR: Program header must precede load segments
+*/

Added: lld/trunk/test/elf/linkerscript/phdrs-no-program.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/linkerscript/phdrs-no-program.test?rev=244743&view=auto
==============================================================================
--- lld/trunk/test/elf/linkerscript/phdrs-no-program.test (added)
+++ lld/trunk/test/elf/linkerscript/phdrs-no-program.test Wed Aug 12 07:31:35 2015
@@ -0,0 +1,25 @@
+/*
+Test when no program segment set it's not generated.
+
+RUN: yaml2obj -format=elf %p/Inputs/simple.o.yaml -o=%t.o
+
+RUN: lld -flavor gnu -target x86_64 -T %s %t.o -static -o %t1
+RUN: llvm-readobj -program-headers %t1 | FileCheck -check-prefix PROGRAM-PHDR %s
+*/
+
+ENTRY(_start)
+
+PHDRS
+{
+    text PT_LOAD;
+}
+
+SECTIONS
+{
+  .text : { *(.text) } :text
+  .data : { *(.data) }
+}
+
+/*
+PROGRAM-PHDR-NOT: Type: PT_PHDR (0x6)
+*/

Added: lld/trunk/test/elf/linkerscript/phdrs-program-flags.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/linkerscript/phdrs-program-flags.test?rev=244743&view=auto
==============================================================================
--- lld/trunk/test/elf/linkerscript/phdrs-program-flags.test (added)
+++ lld/trunk/test/elf/linkerscript/phdrs-program-flags.test Wed Aug 12 07:31:35 2015
@@ -0,0 +1,33 @@
+/*
+Test when program segment contains only FLAGS attribute.
+
+RUN: yaml2obj -format=elf %p/Inputs/simple.o.yaml -o=%t.o
+
+RUN: lld -flavor gnu -target x86_64 -T %s %t.o -static -o %t1
+RUN: llvm-readobj -program-headers %t1 | FileCheck -check-prefix PROGRAM-FLAGS-PHDR %s
+*/
+
+ENTRY(_start)
+
+PHDRS
+{
+    header PT_PHDR PHDRS FLAGS(0x7);
+    text PT_LOAD FILEHDR PHDRS;
+}
+
+SECTIONS
+{
+  .text : { *(.text) } :text
+  .data : { *(.data) }
+}
+
+/*
+PROGRAM-FLAGS-PHDR: ProgramHeader {
+PROGRAM-FLAGS-PHDR: Type: PT_PHDR (0x6)
+PROGRAM-FLAGS-PHDR: Flags [ (0x7)
+PROGRAM-FLAGS-PHDR: PF_R (0x4)
+PROGRAM-FLAGS-PHDR: PF_W (0x2)
+PROGRAM-FLAGS-PHDR: PF_X (0x1)
+PROGRAM-FLAGS-PHDR: ]
+PROGRAM-FLAGS-PHDR: }
+*/

Added: lld/trunk/test/elf/linkerscript/phdrs-program-good-phdrs.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/linkerscript/phdrs-program-good-phdrs.test?rev=244743&view=auto
==============================================================================
--- lld/trunk/test/elf/linkerscript/phdrs-program-good-phdrs.test (added)
+++ lld/trunk/test/elf/linkerscript/phdrs-program-good-phdrs.test Wed Aug 12 07:31:35 2015
@@ -0,0 +1,34 @@
+/*
+Test when program segment contains only PHDRS attribute.
+
+RUN: yaml2obj -format=elf %p/Inputs/simple.o.yaml -o=%t.o
+
+RUN: lld -flavor gnu -target x86_64 -T %s %t.o -static -o %t1
+RUN: llvm-readobj -program-headers %t1 | FileCheck -check-prefix PROGRAM-PHDRS-PHDR %s
+*/
+
+ENTRY(_start)
+
+PHDRS
+{
+    header PT_PHDR PHDRS;
+    text PT_LOAD PHDRS;
+}
+
+SECTIONS
+{
+  .text : { *(.text) } :text
+  .data : { *(.data) }
+}
+
+/*
+PROGRAM-PHDRS-PHDR: ProgramHeader {
+PROGRAM-PHDRS-PHDR: Type: PT_PHDR (0x6)
+PROGRAM-PHDRS-PHDR: VirtualAddress: 0x400040
+PROGRAM-PHDRS-PHDR: MemSize: 168
+PROGRAM-PHDRS-PHDR: Flags [ (0x5)
+PROGRAM-PHDRS-PHDR: PF_R (0x4)
+PROGRAM-PHDRS-PHDR: PF_X (0x1)
+PROGRAM-PHDRS-PHDR: ]
+PROGRAM-PHDRS-PHDR: }
+*/

Added: lld/trunk/test/elf/linkerscript/phdrs-program-no-phdrs.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/linkerscript/phdrs-program-no-phdrs.test?rev=244743&view=auto
==============================================================================
--- lld/trunk/test/elf/linkerscript/phdrs-program-no-phdrs.test (added)
+++ lld/trunk/test/elf/linkerscript/phdrs-program-no-phdrs.test Wed Aug 12 07:31:35 2015
@@ -0,0 +1,26 @@
+/*
+Test when program segment doesn't contain PHDRS attribute.
+
+RUN: yaml2obj -format=elf %p/Inputs/simple.o.yaml -o=%t.o
+
+RUN: not lld -flavor gnu -target x86_64 -T %s %t.o -static -o %t1 &> %t1-error
+RUN: FileCheck -check-prefix PROGRAM-PHDR-NO-PHDRS %s < %t1-error
+*/
+
+ENTRY(_start)
+
+PHDRS
+{
+    header PT_PHDR;
+    text PT_LOAD;
+}
+
+SECTIONS
+{
+  .text : { *(.text) } :text
+  .data : { *(.data) }
+}
+
+/*
+PROGRAM-PHDR-NO-PHDRS: Program header has invalid PHDRS attribute
+*/

Added: lld/trunk/test/elf/linkerscript/phdrs-program-wrong-phdrs.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/linkerscript/phdrs-program-wrong-phdrs.test?rev=244743&view=auto
==============================================================================
--- lld/trunk/test/elf/linkerscript/phdrs-program-wrong-phdrs.test (added)
+++ lld/trunk/test/elf/linkerscript/phdrs-program-wrong-phdrs.test Wed Aug 12 07:31:35 2015
@@ -0,0 +1,26 @@
+/*
+Test when program segment contains PHDRS attribute not mapped to load segment.
+
+RUN: yaml2obj -format=elf %p/Inputs/simple.o.yaml -o=%t.o
+
+RUN: not lld -flavor gnu -target x86_64 -T %s %t.o -static -o %t1 &> %t1-error
+RUN: FileCheck -check-prefix PROGRAM-PHDR-WRONG-PHDRS %s < %t1-error
+*/
+
+ENTRY(_start)
+
+PHDRS
+{
+    header PT_PHDR PHDRS;
+    text PT_LOAD;
+}
+
+SECTIONS
+{
+  .text : { *(.text) } :text
+  .data : { *(.data) }
+}
+
+/*
+PROGRAM-PHDR-WRONG-PHDRS: Program header has invalid PHDRS attribute
+*/




More information about the llvm-commits mailing list