[lld] r243002 - [ELF] Apply segments from linker scripts

Denis Protivensky dprotivensky at accesssoftek.com
Thu Jul 23 03:34:31 PDT 2015


Author: denis-protivensky
Date: Thu Jul 23 05:34:30 2015
New Revision: 243002

URL: http://llvm.org/viewvc/llvm-project?rev=243002&view=rev
Log:
[ELF] Apply segments from linker scripts

Put sections to segments according to linker scripts if available.
Rework the code of TargetLayout::assignSectionsToSegments so it operates
on the given list of segments, which can be either read from linker scripts
or constructed as before.
Handle NONE segments defined in linker scripts by putting corresponding sections
to PT_NULL segment.
Consider flags set for segments through linker scripts.

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

Added:
    lld/trunk/test/elf/linkerscript/phdrs-all-none.test
    lld/trunk/test/elf/linkerscript/phdrs-different.test
    lld/trunk/test/elf/linkerscript/phdrs-flags.test
    lld/trunk/test/elf/linkerscript/phdrs-one-none.test
    lld/trunk/test/elf/linkerscript/phdrs-same-flags.test
    lld/trunk/test/elf/linkerscript/phdrs-same.test
Modified:
    lld/trunk/include/lld/ReaderWriter/LinkerScript.h
    lld/trunk/lib/ReaderWriter/ELF/ARM/ARMTargetHandler.h
    lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.h
    lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetLayout.cpp
    lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetLayout.h
    lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h
    lld/trunk/lib/ReaderWriter/ELF/SegmentChunks.cpp
    lld/trunk/lib/ReaderWriter/ELF/SegmentChunks.h
    lld/trunk/lib/ReaderWriter/ELF/TargetLayout.cpp
    lld/trunk/lib/ReaderWriter/ELF/TargetLayout.h
    lld/trunk/lib/ReaderWriter/LinkerScript.cpp

Modified: lld/trunk/include/lld/ReaderWriter/LinkerScript.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/LinkerScript.h?rev=243002&r1=243001&r2=243002&view=diff
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/LinkerScript.h (original)
+++ lld/trunk/include/lld/ReaderWriter/LinkerScript.h Thu Jul 23 05:34:30 2015
@@ -817,12 +817,12 @@ public:
         _includePHDRs(includePHDRs), _at(at), _flags(flags) {}
 
   StringRef name() const { return _name; }
+  uint64_t type() const { return _type; }
+  uint64_t flags() const { return _flags; }
+  bool isNone() const;
 
   void dump(raw_ostream &os) const;
 
-  /// Special header that discards output sections assigned to it.
-  static const PHDR *NONE;
-
 private:
   StringRef _name;
   uint64_t _type;

Modified: lld/trunk/lib/ReaderWriter/ELF/ARM/ARMTargetHandler.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/ARM/ARMTargetHandler.h?rev=243002&r1=243001&r2=243002&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/ARM/ARMTargetHandler.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/ARM/ARMTargetHandler.h Thu Jul 23 05:34:30 2015
@@ -89,7 +89,7 @@ public:
                                                     inputSectionName));
   }
 
-  SegmentType getSegmentType(Section<ELF32LE> *section) const override {
+  SegmentType getSegmentType(const Section<ELF32LE> *section) const override {
     switch (section->order()) {
     case ORDER_ARM_EXIDX:
       return llvm::ELF::PT_ARM_EXIDX;

Modified: lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.h?rev=243002&r1=243001&r2=243002&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.h Thu Jul 23 05:34:30 2015
@@ -79,7 +79,7 @@ public:
 
   /// \brief get the segment type for the section thats defined by the target
   TargetLayout::SegmentType
-  getSegmentType(Section<ELF32LE> *section) const override {
+  getSegmentType(const Section<ELF32LE> *section) const override {
     if (section->order() == ORDER_SDATA)
       return PT_LOAD;
     return TargetLayout::getSegmentType(section);

Modified: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetLayout.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetLayout.cpp?rev=243002&r1=243001&r2=243002&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetLayout.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetLayout.cpp Thu Jul 23 05:34:30 2015
@@ -33,7 +33,7 @@ AtomSection<ELFT> *MipsTargetLayout<ELFT
 
 template <class ELFT>
 typename TargetLayout<ELFT>::SegmentType
-MipsTargetLayout<ELFT>::getSegmentType(Section<ELFT> *section) const {
+MipsTargetLayout<ELFT>::getSegmentType(const Section<ELFT> *section) const {
   switch (section->order()) {
   case ORDER_MIPS_REGINFO:
     return _abiInfo.hasMipsAbiSection() ? llvm::ELF::PT_LOAD

Modified: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetLayout.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetLayout.h?rev=243002&r1=243001&r2=243002&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetLayout.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetLayout.h Thu Jul 23 05:34:30 2015
@@ -38,7 +38,7 @@ public:
                 typename TargetLayout<ELFT>::SectionOrder order) override;
 
   typename TargetLayout<ELFT>::SegmentType
-  getSegmentType(Section<ELFT> *section) const override;
+  getSegmentType(const Section<ELFT> *section) const override;
 
   /// \brief GP offset relative to .got section.
   uint64_t getGPOffset() const { return 0x7FF0; }

Modified: lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h?rev=243002&r1=243001&r2=243002&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h Thu Jul 23 05:34:30 2015
@@ -85,6 +85,10 @@ public:
     return nullptr;
   }
 
+  const OutputSection<ELFT> *getOutputSection() const {
+    return _outputSection;
+  }
+
   void setOutputSection(OutputSection<ELFT> *os, bool isFirst = false) {
     _outputSection = os;
     _isFirstSectionInOutputSection = isFirst;

Modified: lld/trunk/lib/ReaderWriter/ELF/SegmentChunks.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/SegmentChunks.cpp?rev=243002&r1=243001&r2=243002&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/SegmentChunks.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/SegmentChunks.cpp Thu Jul 23 05:34:30 2015
@@ -23,7 +23,7 @@ template <class ELFT>
 Segment<ELFT>::Segment(const ELFLinkingContext &ctx, StringRef name,
                        const typename TargetLayout<ELFT>::SegmentType type)
     : Chunk<ELFT>(name, Chunk<ELFT>::Kind::ELFSegment, ctx), _segmentType(type),
-      _flags(0), _atomflags(0) {
+      _flags(0), _atomflags(0), _segmentFlags(false) {
   this->_alignment = 1;
   this->_fsize = 0;
   _outputMagic = ctx.getOutputMagic();
@@ -46,17 +46,37 @@ static DefinedAtom::ContentPermissions t
   }
 }
 
+// This function actually is used, but not in all instantiations of Segment.
+LLVM_ATTRIBUTE_UNUSED
+static DefinedAtom::ContentPermissions toAtomPermsSegment(uint64_t flags) {
+  switch (flags & (llvm::ELF::PF_R | llvm::ELF::PF_W | llvm::ELF::PF_X)) {
+  case llvm::ELF::PF_R | llvm::ELF::PF_W | llvm::ELF::PF_X:
+    return DefinedAtom::permRWX;
+  case llvm::ELF::PF_R | llvm::ELF::PF_X:
+    return DefinedAtom::permR_X;
+  case llvm::ELF::PF_R:
+    return DefinedAtom::permR__;
+  case llvm::ELF::PF_R | llvm::ELF::PF_W:
+    return DefinedAtom::permRW_;
+  default:
+    return DefinedAtom::permUnknown;
+  }
+}
+
 template <class ELFT> void Segment<ELFT>::append(Chunk<ELFT> *chunk) {
   _sections.push_back(chunk);
   Section<ELFT> *section = dyn_cast<Section<ELFT>>(chunk);
   if (!section)
     return;
+  if (this->_alignment < section->alignment())
+    this->_alignment = section->alignment();
+
+  if (_segmentFlags)
+    return;
   if (_flags < section->getFlags())
     _flags |= section->getFlags();
   if (_atomflags < toAtomPerms(_flags))
     _atomflags = toAtomPerms(_flags);
-  if (this->_alignment < section->alignment())
-    this->_alignment = section->alignment();
 }
 
 template <class ELFT>
@@ -389,6 +409,9 @@ void Segment<ELFT>::write(ELFWriter *wri
 }
 
 template <class ELFT> int64_t Segment<ELFT>::flags() const {
+  if (_segmentFlags)
+    return (int64_t)_flags;
+
   int64_t fl = 0;
   if (_flags & llvm::ELF::SHF_ALLOC)
     fl |= llvm::ELF::PF_R;
@@ -399,6 +422,13 @@ template <class ELFT> int64_t Segment<EL
   return fl;
 }
 
+template <class ELFT> void Segment<ELFT>::setSegmentFlags(uint64_t flags) {
+  assert(!_segmentFlags && !_flags && "Flags has already been set");
+  _segmentFlags = true;
+  _flags = flags;
+  _atomflags = toAtomPermsSegment(flags);
+}
+
 template <class ELFT> void Segment<ELFT>::finalize() {
   // We want to finalize the segment values for now only for non loadable
   // segments, since those values are not set in the Layout

Modified: lld/trunk/lib/ReaderWriter/ELF/SegmentChunks.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/SegmentChunks.h?rev=243002&r1=243001&r2=243002&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/SegmentChunks.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/SegmentChunks.h Thu Jul 23 05:34:30 2015
@@ -139,6 +139,9 @@ public:
 
   int64_t flags() const;
 
+  // Set segment flags directly.
+  void setSegmentFlags(uint64_t flags);
+
   /// Prepend a generic chunk to the segment.
   void prepend(Chunk<ELFT> *c) {
     _sections.insert(_sections.begin(), c);
@@ -188,6 +191,7 @@ protected:
   typename TargetLayout<ELFT>::SegmentType _segmentType;
   uint64_t _flags;
   int64_t _atomflags;
+  bool _segmentFlags;
   llvm::BumpPtrAllocator _segmentAllocate;
 };
 

Modified: lld/trunk/lib/ReaderWriter/ELF/TargetLayout.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/TargetLayout.cpp?rev=243002&r1=243001&r2=243002&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/TargetLayout.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/TargetLayout.cpp Thu Jul 23 05:34:30 2015
@@ -133,7 +133,7 @@ TargetLayout<ELFT>::getOutputSectionName
 /// \brief Gets the segment for a output section
 template <class ELFT>
 typename TargetLayout<ELFT>::SegmentType
-TargetLayout<ELFT>::getSegmentType(Section<ELFT> *section) const {
+TargetLayout<ELFT>::getSegmentType(const Section<ELFT> *section) const {
   switch (section->order()) {
   case ORDER_INTERP:
     return llvm::ELF::PT_INTERP;
@@ -320,7 +320,6 @@ template <class ELFT> void TargetLayout<
     } else {
       outputSection = new (_allocator.Allocate<OutputSection<ELFT>>())
           OutputSection<ELFT>(section->outputSectionName());
-      checkOutputSectionSegment(outputSection);
       _outputSections.push_back(outputSection);
       outputSectionInsert.first->second = outputSection;
     }
@@ -328,15 +327,66 @@ template <class ELFT> void TargetLayout<
   }
 }
 
-// Check that output section has proper segment set
 template <class ELFT>
-void TargetLayout<ELFT>::checkOutputSectionSegment(
-    const OutputSection<ELFT> *sec) {
+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;
+}
+
+template <class ELFT>
+std::vector<const script::PHDR *>
+TargetLayout<ELFT>::getCustomSegments(const Section<ELFT> *section) const {
+  auto sec = section->getOutputSection();
+  assert(sec && "Output section should be already set for input section");
+  return getCustomSegments(sec);
+}
+
+template <class ELFT>
+std::vector<typename TargetLayout<ELFT>::SegmentKey>
+TargetLayout<ELFT>::getSegmentsForSection(const OutputSection<ELFT> *os,
+                                          const Section<ELFT> *sec) const {
+  std::vector<SegmentKey> segKeys;
+  auto phdrs = getCustomSegments(os);
+  if (!phdrs.empty()) {
+    if (phdrs.size() == 1 && phdrs[0]->isNone()) {
+      segKeys.emplace_back("NONE", llvm::ELF::PT_NULL, 0, false);
+      return segKeys;
+    }
+
+    for (auto phdr : phdrs) {
+      segKeys.emplace_back(phdr->name(), phdr->type(), phdr->flags(), true);
+    }
+    return segKeys;
+  }
+
+  uint64_t flags = getLookupSectionFlags(os);
+  int64_t segmentType = getSegmentType(sec);
+  StringRef segmentName = sec->segmentKindToStr();
+
+  // We need a separate segment for sections that don't have
+  // the segment type to be PT_LOAD
+  if (segmentType != llvm::ELF::PT_LOAD)
+    segKeys.emplace_back(segmentName, segmentType, flags, false);
+
+  if (segmentType == llvm::ELF::PT_NULL)
+    return segKeys;
+
+  // If the output magic is set to OutputMagic::NMAGIC or
+  // OutputMagic::OMAGIC, Place the data alongside text in one single
+  // segment
+  ELFLinkingContext::OutputMagic outputMagic = _ctx.getOutputMagic();
+  if (outputMagic == ELFLinkingContext::OutputMagic::NMAGIC ||
+      outputMagic == ELFLinkingContext::OutputMagic::OMAGIC)
+    flags =
+        llvm::ELF::SHF_EXECINSTR | llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE;
+
+  segKeys.emplace_back("LOAD", llvm::ELF::PT_LOAD, flags, false);
+  return segKeys;
 }
 
 template <class ELFT>
@@ -356,7 +406,6 @@ TargetLayout<ELFT>::getLookupSectionFlag
 
 template <class ELFT> void TargetLayout<ELFT>::assignSectionsToSegments() {
   ScopedTask task(getDefaultDomain(), "assignSectionsToSegments");
-  ELFLinkingContext::OutputMagic outputMagic = _ctx.getOutputMagic();
   // sort the sections by their order as defined by the layout
   sortInputSections();
 
@@ -381,66 +430,40 @@ template <class ELFT> void TargetLayout<
         continue;
 
       osi->setLoadableSection(section->isLoadableSection());
-
-      // Get the segment type for the section
-      int64_t segmentType = getSegmentType(section);
-
       osi->setHasSegment();
-      section->setSegmentType(segmentType);
-      StringRef segmentName = section->segmentKindToStr();
 
-      uint64_t lookupSectionFlag = getLookupSectionFlags(osi);
-
-      Segment<ELFT> *segment;
-      // We need a separate segment for sections that don't have
-      // the segment type to be PT_LOAD
-      if (segmentType != llvm::ELF::PT_LOAD) {
-        const AdditionalSegmentKey key(segmentType, lookupSectionFlag);
-        const std::pair<AdditionalSegmentKey, Segment<ELFT> *>
-            additionalSegment(key, nullptr);
-        std::pair<typename AdditionalSegmentMapT::iterator, bool>
-            additionalSegmentInsert(
-                _additionalSegmentMap.insert(additionalSegment));
-        if (!additionalSegmentInsert.second) {
-          segment = additionalSegmentInsert.first->second;
+      auto segKeys = getSegmentsForSection(osi, section);
+      assert(!segKeys.empty() && "Must always be at least one segment");
+      section->setSegmentType(segKeys[0]._type);
+
+      for (auto key : segKeys) {
+        // Try to find non-load (real) segment type if possible
+        if (key._type != llvm::ELF::PT_LOAD)
+          section->setSegmentType(key._type);
+
+        const std::pair<SegmentKey, Segment<ELFT> *> currentSegment(key,
+                                                                    nullptr);
+        std::pair<typename SegmentMapT::iterator, bool> segmentInsert(
+            _segmentMap.insert(currentSegment));
+        Segment<ELFT> *segment;
+        if (!segmentInsert.second) {
+          segment = segmentInsert.first->second;
         } else {
-          segment =
-              new (_allocator) Segment<ELFT>(_ctx, segmentName, segmentType);
-          additionalSegmentInsert.first->second = segment;
+          segment = new (_allocator) Segment<ELFT>(_ctx, key._name, key._type);
+          if (key._segmentFlags)
+            segment->setSegmentFlags(key._flags);
+          segmentInsert.first->second = segment;
           _segments.push_back(segment);
         }
+        if (key._type == llvm::ELF::PT_LOAD) {
+          // Insert chunks with linker script expressions that occur at this
+          // point, just before appending a new input section
+          addExtraChunksToSegment(segment, section->archivePath(),
+                                  section->memberPath(),
+                                  section->inputSectionName());
+        }
         segment->append(section);
       }
-      if (segmentType == llvm::ELF::PT_NULL)
-        continue;
-
-      // If the output magic is set to OutputMagic::NMAGIC or
-      // OutputMagic::OMAGIC, Place the data alongside text in one single
-      // segment
-      if (outputMagic == ELFLinkingContext::OutputMagic::NMAGIC ||
-          outputMagic == ELFLinkingContext::OutputMagic::OMAGIC)
-        lookupSectionFlag = llvm::ELF::SHF_EXECINSTR | llvm::ELF::SHF_ALLOC |
-                            llvm::ELF::SHF_WRITE;
-
-      // Use the flags of the merged Section for the segment
-      const SegmentKey key("PT_LOAD", lookupSectionFlag);
-      const std::pair<SegmentKey, Segment<ELFT> *> currentSegment(key, nullptr);
-      std::pair<typename SegmentMapT::iterator, bool> segmentInsert(
-          _segmentMap.insert(currentSegment));
-      if (!segmentInsert.second) {
-        segment = segmentInsert.first->second;
-      } else {
-        segment =
-            new (_allocator) Segment<ELFT>(_ctx, "PT_LOAD", llvm::ELF::PT_LOAD);
-        segmentInsert.first->second = segment;
-        _segments.push_back(segment);
-      }
-      // Insert chunks with linker script expressions that occur at this
-      // point, just before appending a new input section
-      addExtraChunksToSegment(segment, section->archivePath(),
-                              section->memberPath(),
-                              section->inputSectionName());
-      segment->append(section);
     }
   }
   if (_ctx.isDynamic() && !_ctx.isDynamicLibrary()) {

Modified: lld/trunk/lib/ReaderWriter/ELF/TargetLayout.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/TargetLayout.h?rev=243002&r1=243001&r2=243002&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/TargetLayout.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/TargetLayout.h Thu Jul 23 05:34:30 2015
@@ -106,36 +106,31 @@ public:
   typedef typename std::vector<Chunk<ELFT> *>::iterator ChunkIter;
   typedef typename std::vector<Segment<ELFT> *>::iterator SegmentIter;
 
-  // The additional segments are used to figure out
-  // if there is a segment by that type already created
-  // For example : PT_TLS, we have two sections .tdata/.tbss
-  // that are part of PT_TLS, we need to create this additional
-  // segment only once
-  typedef std::pair<int64_t, int64_t> AdditionalSegmentKey;
-  // The segments are created using
-  // SegmentName, Segment flags
-  typedef std::pair<StringRef, int64_t> SegmentKey;
-
-  // HashKey for the Segment
-  class SegmentHashKey {
-  public:
-    int64_t operator() (const SegmentKey &k) const {
-      // k.first = SegmentName
-      // k.second = SegmentFlags
-      return llvm::hash_combine(k.first, k.second);
+  // Properties used during segment creation
+  struct SegmentKey {
+    SegmentKey(StringRef name, int64_t type, uint64_t flags, bool segFlags)
+        : _name(name), _type(type), _flags(flags),
+          _segmentFlags(segFlags && flags != 0) {}
+    StringRef _name = "";
+    int64_t _type = 0;
+    uint64_t _flags = 0;
+    bool _segmentFlags = false;
+  };
+
+  struct SegmentKeyHash {
+    int64_t operator()(const SegmentKey &k) const {
+      return llvm::hash_combine(k._name, k._type, k._flags);
     }
   };
 
-  class AdditionalSegmentHashKey {
-  public:
-    int64_t operator()(const AdditionalSegmentKey &k) const {
-      // k.first = SegmentName
-      // k.second = SegmentFlags
-      return llvm::hash_combine(k.first, k.second);
+  struct SegmentKeyEq {
+    bool operator()(const SegmentKey &lhs, const SegmentKey &rhs) const {
+      return ((lhs._name == rhs._name) && (lhs._type == rhs._type) &&
+              (lhs._flags == rhs._flags));
     }
   };
 
-  // Output Sections contain the map of Sectionnames to a vector of sections,
+  // Output Sections contain the map of Section names to a vector of sections,
   // that have been merged to form a single section
   typedef llvm::StringMap<OutputSection<ELFT> *> OutputSectionMapT;
   typedef
@@ -143,10 +138,8 @@ public:
 
   typedef std::unordered_map<SectionKey, AtomSection<ELFT> *, SectionKeyHash,
                              SectionKeyEq> SectionMapT;
-  typedef std::unordered_map<AdditionalSegmentKey, Segment<ELFT> *,
-                             AdditionalSegmentHashKey> AdditionalSegmentMapT;
-  typedef std::unordered_map<SegmentKey, Segment<ELFT> *, SegmentHashKey>
-  SegmentMapT;
+  typedef std::unordered_map<SegmentKey, Segment<ELFT> *, SegmentKeyHash,
+                             SegmentKeyEq> SegmentMapT;
 
   typedef typename std::vector<AtomLayout *>::iterator AbsoluteAtomIterT;
 
@@ -177,7 +170,7 @@ public:
              const DefinedAtom *da);
 
   /// \brief Gets the segment for a output section
-  virtual SegmentType getSegmentType(Section<ELFT> *section) const;
+  virtual SegmentType getSegmentType(const Section<ELFT> *section) const;
 
   /// \brief Returns true/false depending on whether the section has a Output
   //         segment or not
@@ -209,8 +202,17 @@ public:
   // Output sections with the same name into a OutputSection
   void createOutputSections();
 
-  // Check that output section has proper segment set
-  void checkOutputSectionSegment(const OutputSection<ELFT> *sec);
+  // Query for custom segments of the given section
+  std::vector<const script::PHDR *>
+  getCustomSegments(const Section<ELFT> *section) const;
+
+  // Query for custom segments of the given output section
+  std::vector<const script::PHDR *>
+  getCustomSegments(const OutputSection<ELFT> *sec) const;
+
+  // Query for segments based on output and input sections
+  std::vector<SegmentKey> getSegmentsForSection(const OutputSection<ELFT> *os,
+                                                const Section<ELFT> *sec) const;
 
   /// \brief Sort the sections by their order as defined by the layout,
   /// preparing all sections to be assigned to a segment.
@@ -312,7 +314,6 @@ protected:
   llvm::BumpPtrAllocator _allocator;
   SectionMapT _sectionMap;
   OutputSectionMapT _outputSectionMap;
-  AdditionalSegmentMapT _additionalSegmentMap;
   SegmentMapT _segmentMap;
   std::vector<Chunk<ELFT> *> _sections;
   std::vector<Segment<ELFT> *> _segments;

Modified: lld/trunk/lib/ReaderWriter/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/LinkerScript.cpp?rev=243002&r1=243001&r2=243002&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/LinkerScript.cpp (original)
+++ lld/trunk/lib/ReaderWriter/LinkerScript.cpp Thu Jul 23 05:34:30 2015
@@ -937,6 +937,13 @@ void OutputSectionDescription::dump(raw_
   }
 }
 
+// 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)
@@ -953,9 +960,6 @@ void PHDR::dump(raw_ostream &os) const {
   os << ";\n";
 }
 
-static PHDR none("NONE", 0, false, false, NULL, 0);
-const PHDR *PHDR::NONE = &none;
-
 void PHDRS::dump(raw_ostream &os) const {
   os << "PHDRS\n{\n";
   for (auto &&phdr : _phdrs) {
@@ -2736,11 +2740,11 @@ std::error_code Sema::buildSectionToPHDR
 
   // Add NONE header to the map provided there's no user-defined
   // header with the same name.
-  if (!_sectionToPHDR.count(PHDR::NONE->name()))
-    phdrs[PHDR::NONE->name()] = PHDR::NONE;
+  if (!_sectionToPHDR.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 };
+  llvm::SmallVector<const PHDR *, 2> phdrsCur, phdrsLast { &PHDR_NONE };
   for (const Command *cmd : _layoutCommands) {
     auto osd = dyn_cast<OutputSectionDescription>(cmd);
     if (!osd || osd->isDiscarded())

Added: lld/trunk/test/elf/linkerscript/phdrs-all-none.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/linkerscript/phdrs-all-none.test?rev=243002&view=auto
==============================================================================
--- lld/trunk/test/elf/linkerscript/phdrs-all-none.test (added)
+++ lld/trunk/test/elf/linkerscript/phdrs-all-none.test Thu Jul 23 05:34:30 2015
@@ -0,0 +1,26 @@
+/*
+Test when all segments are marked as NONE.
+
+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-objdump -section-headers %t1 | FileCheck -check-prefix NONE-ALL-PHDRS %s
+*/
+
+ENTRY(_start)
+
+PHDRS
+{
+    text PT_LOAD;
+}
+
+SECTIONS
+{
+  .text : { *(.text) } :NONE
+  .data : { *(.data) }
+}
+
+/*
+NONE-ALL-PHDRS: .text {{[0-9a-f]+}} 0000000000000000
+NONE-ALL-PHDRS: .data {{[0-9a-f]+}} 000000000000002c
+*/

Added: lld/trunk/test/elf/linkerscript/phdrs-different.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/linkerscript/phdrs-different.test?rev=243002&view=auto
==============================================================================
--- lld/trunk/test/elf/linkerscript/phdrs-different.test (added)
+++ lld/trunk/test/elf/linkerscript/phdrs-different.test Thu Jul 23 05:34:30 2015
@@ -0,0 +1,45 @@
+/*
+Test sections put to different segments.
+
+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-objdump -section-headers %t1 | FileCheck -check-prefix DIFF-PHDRS-SECS %s
+RUN: llvm-readobj -program-headers %t1 | FileCheck -check-prefix DIFF-PHDRS-HDRS %s
+*/
+
+ENTRY(_start)
+
+PHDRS
+{
+  text PT_LOAD;
+  data PT_LOAD;
+}
+
+SECTIONS
+{
+  .text : { *(.text) } :text
+  .data : { *(.data) } :data
+}
+
+/*
+DIFF-PHDRS-SECS: .text {{[0-9a-f]+}} 00000000004000e8
+DIFF-PHDRS-SECS: .data {{[0-9a-f]+}} 0000000000401000
+
+DIFF-PHDRS-HDRS: ProgramHeader {
+DIFF-PHDRS-HDRS: Type: PT_LOAD (0x1)
+DIFF-PHDRS-HDRS: VirtualAddress: 0x400000
+DIFF-PHDRS-HDRS: Flags [ (0x5)
+DIFF-PHDRS-HDRS: PF_R (0x4)
+DIFF-PHDRS-HDRS: PF_X (0x1)
+DIFF-PHDRS-HDRS: ]
+DIFF-PHDRS-HDRS: }
+DIFF-PHDRS-HDRS: ProgramHeader {
+DIFF-PHDRS-HDRS: Type: PT_LOAD (0x1)
+DIFF-PHDRS-HDRS: VirtualAddress: 0x401000
+DIFF-PHDRS-HDRS: Flags [ (0x6)
+DIFF-PHDRS-HDRS: PF_R (0x4)
+DIFF-PHDRS-HDRS: PF_W (0x2)
+DIFF-PHDRS-HDRS: ]
+DIFF-PHDRS-HDRS: }
+*/

Added: lld/trunk/test/elf/linkerscript/phdrs-flags.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/linkerscript/phdrs-flags.test?rev=243002&view=auto
==============================================================================
--- lld/trunk/test/elf/linkerscript/phdrs-flags.test (added)
+++ lld/trunk/test/elf/linkerscript/phdrs-flags.test Thu Jul 23 05:34:30 2015
@@ -0,0 +1,46 @@
+/*
+Test sections put to different segments with FLAGS attribute set.
+
+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-objdump -section-headers %t1 | FileCheck -check-prefix FLAGS-PHDRS-SECS %s
+RUN: llvm-readobj -program-headers %t1 | FileCheck -check-prefix FLAGS-PHDRS-HDRS %s
+*/
+
+ENTRY(_start)
+
+PHDRS
+{
+    text PT_LOAD FLAGS(0x5);
+    data PT_LOAD FLAGS(0x7);
+}
+
+SECTIONS
+{
+  .text : { *(.text) } :text
+  .data : { *(.data) } :data
+}
+
+/*
+FLAGS-PHDRS-SECS: .text {{[0-9a-f]+}} 0000000000401000
+FLAGS-PHDRS-SECS: .data {{[0-9a-f]+}} 00000000004000e8
+
+FLAGS-PHDRS-HDRS: ProgramHeader {
+FLAGS-PHDRS-HDRS: Type: PT_LOAD (0x1)
+FLAGS-PHDRS-HDRS: VirtualAddress: 0x400000
+FLAGS-PHDRS-HDRS: Flags [ (0x7)
+FLAGS-PHDRS-HDRS: PF_R (0x4)
+FLAGS-PHDRS-HDRS: PF_W (0x2)
+FLAGS-PHDRS-HDRS: PF_X (0x1)
+FLAGS-PHDRS-HDRS: ]
+FLAGS-PHDRS-HDRS: }
+FLAGS-PHDRS-HDRS: ProgramHeader {
+FLAGS-PHDRS-HDRS: Type: PT_LOAD (0x1)
+FLAGS-PHDRS-HDRS: VirtualAddress: 0x401000
+FLAGS-PHDRS-HDRS: Flags [ (0x5)
+FLAGS-PHDRS-HDRS: PF_R (0x4)
+FLAGS-PHDRS-HDRS: PF_X (0x1)
+FLAGS-PHDRS-HDRS: ]
+FLAGS-PHDRS-HDRS: }
+*/

Added: lld/trunk/test/elf/linkerscript/phdrs-one-none.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/linkerscript/phdrs-one-none.test?rev=243002&view=auto
==============================================================================
--- lld/trunk/test/elf/linkerscript/phdrs-one-none.test (added)
+++ lld/trunk/test/elf/linkerscript/phdrs-one-none.test Thu Jul 23 05:34:30 2015
@@ -0,0 +1,36 @@
+/*
+Test when one segment is marked as NONE.
+
+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-objdump -section-headers %t1 | FileCheck -check-prefix NONE-PHDRS-SECS %s
+RUN: llvm-readobj -program-headers %t1 | FileCheck -check-prefix NONE-PHDRS-HDRS %s
+*/
+
+ENTRY(_start)
+
+PHDRS
+{
+  text PT_LOAD;
+}
+
+SECTIONS
+{
+  .text : { *(.text) } :text
+  .data : { *(.data) } :NONE
+}
+
+/*
+NONE-PHDRS-SECS: .text {{[0-9a-f]+}} 00000000004000b0
+NONE-PHDRS-SECS: .data {{[0-9a-f]+}} 0000000000000000
+
+NONE-PHDRS-HDRS: ProgramHeader {
+NONE-PHDRS-HDRS: Type: PT_LOAD (0x1)
+NONE-PHDRS-HDRS: VirtualAddress: 0x400000
+NONE-PHDRS-HDRS: Flags [ (0x5)
+NONE-PHDRS-HDRS: PF_R (0x4)
+NONE-PHDRS-HDRS: PF_X (0x1)
+NONE-PHDRS-HDRS: ]
+NONE-PHDRS-HDRS: }
+*/

Added: lld/trunk/test/elf/linkerscript/phdrs-same-flags.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/linkerscript/phdrs-same-flags.test?rev=243002&view=auto
==============================================================================
--- lld/trunk/test/elf/linkerscript/phdrs-same-flags.test (added)
+++ lld/trunk/test/elf/linkerscript/phdrs-same-flags.test Thu Jul 23 05:34:30 2015
@@ -0,0 +1,35 @@
+/*
+Test sections put to same segment with FLAGS attribute set.
+
+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-objdump -section-headers %t1 | FileCheck -check-prefix FLAGS-PHDRS-SECS %s
+RUN: llvm-readobj -program-headers %t1 | FileCheck -check-prefix FLAGS-PHDRS-HDRS %s
+*/
+
+ENTRY(_start)
+
+PHDRS
+{
+    text PT_LOAD FLAGS(0x4);
+}
+
+SECTIONS
+{
+  .text : { *(.text) } :text
+  .data : { *(.data) }
+}
+
+/*
+FLAGS-PHDRS-SECS: .text {{[0-9a-f]+}} 00000000004000b0
+FLAGS-PHDRS-SECS: .data {{[0-9a-f]+}} 00000000004000dc
+
+FLAGS-PHDRS-HDRS: ProgramHeader {
+FLAGS-PHDRS-HDRS: Type: PT_LOAD (0x1)
+FLAGS-PHDRS-HDRS: VirtualAddress: 0x400000
+FLAGS-PHDRS-HDRS: Flags [ (0x4)
+FLAGS-PHDRS-HDRS: PF_R (0x4)
+FLAGS-PHDRS-HDRS: ]
+FLAGS-PHDRS-HDRS: }
+*/

Added: lld/trunk/test/elf/linkerscript/phdrs-same.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/linkerscript/phdrs-same.test?rev=243002&view=auto
==============================================================================
--- lld/trunk/test/elf/linkerscript/phdrs-same.test (added)
+++ lld/trunk/test/elf/linkerscript/phdrs-same.test Thu Jul 23 05:34:30 2015
@@ -0,0 +1,36 @@
+/*
+Test sections put to same segment.
+
+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-objdump -section-headers %t1 | FileCheck -check-prefix SAME-PHDRS-SECS %s
+RUN: llvm-readobj -program-headers %t1 | FileCheck -check-prefix SAME-PHDRS-HDRS %s
+*/
+
+ENTRY(_start)
+
+PHDRS
+{
+  text PT_LOAD;
+}
+
+SECTIONS
+{
+  .text : { *(.text) } :text
+  .data : { *(.data) }
+}
+
+/*
+SAME-PHDRS-SECS: .text {{[0-9a-f]+}} 00000000004000b0
+SAME-PHDRS-SECS: .data {{[0-9a-f]+}} 00000000004000dc
+
+SAME-PHDRS-HDRS: ProgramHeader {
+SAME-PHDRS-HDRS: Type: PT_LOAD (0x1)
+SAME-PHDRS-HDRS: VirtualAddress: 0x400000
+SAME-PHDRS-HDRS: Flags [ (0x5)
+SAME-PHDRS-HDRS: PF_R (0x4)
+SAME-PHDRS-HDRS: PF_X (0x1)
+SAME-PHDRS-HDRS: ]
+SAME-PHDRS-HDRS: }
+*/





More information about the llvm-commits mailing list