[lld] r221233 - [ELF] Fix program headers.

Eric Christopher echristo at gmail.com
Tue Nov 4 15:17:41 PST 2014


Huh, why not?

-eric

On Tue Nov 04 2014 at 3:15:54 PM Shankar Easwaran <shankare at codeaurora.org>
wrote:

>  Hi Eric,
>
> For the complete fix to the issue, the Writer had to be cleanup as well. I
> wasnot able to separate the two functionalities.
>
> Shankar Easwaran
>
>
> On 11/4/2014 4:24 PM, Eric Christopher wrote:
>
> Hi Shankar,
>
> Can you please try to separate out distinct patches in the future? The
> "cleanup" aspects of this patch make it hard to determine what changed.
>
> -eric
>
> On Mon Nov 03 2014 at 8:10:35 PM Shankar Easwaran <shankarke at gmail.com> <shankarke at gmail.com>
> wrote:
>
>
>  Author: shankare
> Date: Mon Nov  3 21:57:04 2014
> New Revision: 221233
>
> URL: http://llvm.org/viewvc/llvm-project?rev=221233&view=rev
> Log:
> [ELF] Fix program headers.
>
> The ELF writer creates a invalid binary for few cases with large filesize
> and
> memory size for segments. This patch addresses the functionality and
> updates the
> test. This patch also cleans up parts of the ELF writer for future
> enhancements
> to support Linker scripts.
>
> Modified:
>     lld/trunk/lib/ReaderWriter/ELF/Chunk.h
>     lld/trunk/lib/ReaderWriter/ELF/DefaultLayout.h
>     lld/trunk/lib/ReaderWriter/ELF/HeaderChunks.h
>     lld/trunk/lib/ReaderWriter/ELF/Layout.h
>     lld/trunk/lib/ReaderWriter/ELF/OutputELFWriter.h
>     lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h
>     lld/trunk/lib/ReaderWriter/ELF/SegmentChunks.h
>     lld/trunk/test/elf/phdr.test
>
> Modified: lld/trunk/lib/ReaderWriter/ELF/Chunk.h
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/
> ReaderWriter/ELF/Chunk.h?rev=221233&r1=221232&r2=221233&view=diff
> ============================================================
> ==================
> --- lld/trunk/lib/ReaderWriter/ELF/Chunk.h (original)
> +++ lld/trunk/lib/ReaderWriter/ELF/Chunk.h Mon Nov  3 21:57:04 2014
> @@ -52,9 +52,10 @@ public:
>    StringRef name() const { return _name; }
>    // Kind of chunk
>    Kind kind() const { return _kind; }
> -  uint64_t        fileSize() const { return _fsize; }
> -  void            setAlign(uint64_t align) { _align2 = align; }
> -  uint64_t        align2() const { return _align2; }
> +  virtual uint64_t fileSize() const { return _fsize; }
> +  virtual void setFileSize(uint64_t sz) { _fsize = sz; }
> +  virtual void setAlign(uint64_t align) { _align2 = align; }
> +  virtual uint64_t align2() const { return _align2; }
>
>    // The ordinal value of the chunk
>    uint64_t            ordinal() const { return _ordinal;}
> @@ -66,8 +67,8 @@ public:
>    uint64_t            fileOffset() const { return _fileoffset; }
>    void               setFileOffset(uint64_t offset) { _fileoffset =
> offset; }
>    // Output start address of the chunk
> -  void               setVAddr(uint64_t start) { _start = start; }
> -  uint64_t            virtualAddr() const { return _start; }
> +  virtual void setVirtualAddr(uint64_t start) { _start = start; }
> +  virtual uint64_t virtualAddr() const { return _start; }
>    // Memory size of the chunk
>    uint64_t memSize() const { return _msize; }
>    void setMemSize(uint64_t msize) { _msize = msize; }
>
> Modified: lld/trunk/lib/ReaderWriter/ELF/DefaultLayout.h
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/
> DefaultLayout.h?rev=221233&r1=221232&r2=221233&view=diff
> ============================================================
> ==================
> --- lld/trunk/lib/ReaderWriter/ELF/DefaultLayout.h (original)
> +++ lld/trunk/lib/ReaderWriter/ELF/DefaultLayout.h Mon Nov  3 21:57:04
> 2014
> @@ -215,9 +215,7 @@ public:
>
>    void assignVirtualAddress() override;
>
> -  void assignOffsetsForMiscSections();
> -
> -  void assignFileOffsets() override;
> +  void assignFileOffsetsForMiscSections();
>
>    /// Inline functions
>    inline range<AbsoluteAtomIterT> absoluteAtoms() { return
> _absoluteAtoms; }
> @@ -734,32 +732,15 @@ template <class ELFT> void DefaultLayout
>    }
>  }
>
> -template <class ELFT> void DefaultLayout<ELFT>::assignFileOffsets() {
> -  // TODO: Do we want to give a chance for the targetHandlers
> -  // to sort segments in an arbitrary order?
> -  std::sort(_segments.begin(), _segments.end(), Segment<ELFT>::
> compareSegments);
> -  int ordinal = 0;
> -  // Compute the number of segments that might be needed, so that the
> -  // size of the program header can be computed
> -  uint64_t offset = 0;
> -  for (auto si : _segments) {
> -    si->setOrdinal(++ordinal);
> -    // Don't assign offsets for segments that are not loadable
> -    if (si->segmentType() != llvm::ELF::PT_LOAD)
> -      continue;
> -    si->assignOffsets(offset);
> -    offset += si->fileSize();
> -  }
> -}
> -
>  template<class ELFT>
>  void
>  DefaultLayout<ELFT>::assignVirtualAddress() {
>    if (_segments.empty())
>      return;
>
> +  std::sort(_segments.begin(), _segments.end(), Segment<ELFT>::
> compareSegments);
> +
>    uint64_t virtualAddress = _context.getBaseAddress();
> -  ELFLinkingContext::OutputMagic outputMagic = _context.getOutputMagic();
>
>    // HACK: This is a super dirty hack. The elf header and program header
> are
>    // not part of a section, but we need them to be loaded at the base
> address
> @@ -777,6 +758,7 @@ DefaultLayout<ELFT>::assignVirtualAddres
>    firstLoadSegment->prepend(_programHeader);
>    firstLoadSegment->prepend(_elfHeader);
>    bool newSegmentHeaderAdded = true;
> +  bool virtualAddressAssigned = false;
>    while (true) {
>      for (auto si : _segments) {
>        si->finalize();
> @@ -784,24 +766,10 @@ DefaultLayout<ELFT>::assignVirtualAddres
>        if (si->segmentType() != llvm::ELF::PT_NULL)
>          newSegmentHeaderAdded = _programHeader->addSegment(si);
>      }
> -    if (!newSegmentHeaderAdded)
> +    if (!newSegmentHeaderAdded && virtualAddressAssigned)
>        break;
> -    uint64_t fileoffset = 0;
> +    virtualAddressAssigned = true;
>      uint64_t address = virtualAddress;
> -    // Fix the offsets after adding the program header
> -    for (auto &si : _segments) {
> -      if ((si->segmentType() != llvm::ELF::PT_LOAD) &&
> -          (si->segmentType() != llvm::ELF::PT_NULL))
> -        continue;
> -      // Align the segment to a page boundary only if the output mode is
> -      // not OutputMagic::NMAGIC/OutputMagic::OMAGIC
> -      if (outputMagic != ELFLinkingContext::OutputMagic::NMAGIC &&
> -          outputMagic != ELFLinkingContext::OutputMagic::OMAGIC)
> -        fileoffset =
> -            llvm::RoundUpToAlignment(fileoffset, _context.getPageSize());
> -      si->assignOffsets(fileoffset);
> -      fileoffset = si->fileOffset() + si->fileSize();
> -    }
>      // start assigning virtual addresses
>      for (auto &si : _segments) {
>        if ((si->segmentType() != llvm::ELF::PT_LOAD) &&
> @@ -809,22 +777,19 @@ DefaultLayout<ELFT>::assignVirtualAddres
>          continue;
>
>        if (si->segmentType() == llvm::ELF::PT_NULL) {
> -        // Handle Non allocatable sections.
> -        uint64_t nonLoadableAddr = 0;
> -        si->setVAddr(nonLoadableAddr);
> -        si->assignVirtualAddress(nonLoadableAddr);
> +        si->assignVirtualAddress(0 /*non loadable*/);
>        } else {
> -        si->setVAddr(virtualAddress);
> -        // The first segment has the virtualAddress set to the base
> address as
> -        // we have added the file header and the program header don't
> align the
> -        // first segment to the pagesize
>          si->assignVirtualAddress(address);
> -        si->setMemSize(address - virtualAddress);
> -        if (outputMagic != ELFLinkingContext::OutputMagic::NMAGIC &&
> -            outputMagic != ELFLinkingContext::OutputMagic::OMAGIC)
> -          virtualAddress =
> -              llvm::RoundUpToAlignment(address, _context.getPageSize());
>        }
> +      address = si->virtualAddr() + si->memSize();
> +    }
> +    uint64_t fileoffset = 0;
> +    for (auto &si : _segments) {
> +      if ((si->segmentType() != llvm::ELF::PT_LOAD) &&
> +          (si->segmentType() != llvm::ELF::PT_NULL))
> +        continue;
> +      si->assignFileOffsets(fileoffset);
> +      fileoffset = si->fileOffset() + si->fileSize();
>      }
>      _programHeader->resetProgramHeaders();
>    }
> @@ -833,7 +798,7 @@ DefaultLayout<ELFT>::assignVirtualAddres
>    for (auto &si : _sections) {
>      section = dyn_cast<Section<ELFT>>(si);
>      if (section && DefaultLayout<ELFT>::hasOutputSegment(section))
> -      section->assignOffsets(section->fileOffset());
> +      section->assignFileOffsets(section->fileOffset());
>    }
>    // Set the size of the merged Sections
>    for (auto msi : _mergedSections) {
> @@ -873,9 +838,8 @@ DefaultLayout<ELFT>::assignVirtualAddres
>    }
>  }
>
> -template<class ELFT>
> -void
> -DefaultLayout<ELFT>::assignOffsetsForMiscSections() {
> +template <class ELFT>
> +void DefaultLayout<ELFT>::assignFileOffsetsForMiscSections() {
>    uint64_t fileoffset = 0;
>    uint64_t size = 0;
>    for (auto si : _segments) {
> @@ -894,7 +858,7 @@ DefaultLayout<ELFT>::assignOffsetsForMis
>        continue;
>      fileoffset = llvm::RoundUpToAlignment(fileoffset, si->align2());
>      si->setFileOffset(fileoffset);
> -    si->setVAddr(0);
> +    si->setVirtualAddr(0);
>      fileoffset += si->fileSize();
>    }
>  }
>
> Modified: lld/trunk/lib/ReaderWriter/ELF/HeaderChunks.h
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/
> ReaderWriter/ELF/HeaderChunks.h?rev=221233&r1=221232&r2=221233&view=diff
> ============================================================
> ==================
> --- lld/trunk/lib/ReaderWriter/ELF/HeaderChunks.h (original)
> +++ lld/trunk/lib/ReaderWriter/ELF/HeaderChunks.h Mon Nov  3 21:57:04 2014
> @@ -43,7 +43,7 @@ public:
>    void e_shentsize(uint16_t shentsize) { _eh.e_shentsize = shentsize; }
>    void e_shnum(uint16_t shnum)         { _eh.e_shnum = shnum; }
>    void e_shstrndx(uint16_t shstrndx)   { _eh.e_shstrndx = shstrndx; }
> -  uint64_t  fileSize()                 { return sizeof (Elf_Ehdr); }
> +  uint64_t fileSize() const { return sizeof(Elf_Ehdr); }
>
>    static inline bool classof(const Chunk<ELFT> *c) {
>      return c->Kind() == Chunk<ELFT>::Kind::ELFHeader;
> @@ -125,9 +125,7 @@ public:
>
>    void resetProgramHeaders() { _phi = _ph.begin(); }
>
> -  uint64_t  fileSize() {
> -    return sizeof(Elf_Phdr) * _ph.size();
> -  }
> +  uint64_t fileSize() const { return sizeof(Elf_Phdr) * _ph.size(); }
>
>    static inline bool classof(const Chunk<ELFT> *c) {
>      return c->Kind() == Chunk<ELFT>::Kind::ProgramHeader;
> @@ -271,7 +269,7 @@ public:
>
>    void finalize() {}
>
> -  inline uint64_t fileSize() { return sizeof(Elf_Shdr) *
> _sectionInfo.size(); }
> +  uint64_t fileSize() const { return sizeof(Elf_Shdr) *
> _sectionInfo.size(); }
>
>    inline uint64_t entsize() {
>      return sizeof(Elf_Shdr);
>
> Modified: lld/trunk/lib/ReaderWriter/ELF/Layout.h
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/
> ReaderWriter/ELF/Layout.h?rev=221233&r1=221232&r2=221233&view=diff
> ============================================================
> ==================
> --- lld/trunk/lib/ReaderWriter/ELF/Layout.h (original)
> +++ lld/trunk/lib/ReaderWriter/ELF/Layout.h Mon Nov  3 21:57:04 2014
> @@ -47,8 +47,6 @@ public:
>    virtual void assignSectionsToSegments() = 0;
>    /// associates a virtual address to the segment, section, and the atom
>    virtual void assignVirtualAddress() = 0;
> -  /// associates a file offset to the segment, section and the atom
> -  virtual void assignFileOffsets() = 0;
>
>  public:
>    Layout() {}
>
> Modified: lld/trunk/lib/ReaderWriter/ELF/OutputELFWriter.h
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/
> OutputELFWriter.h?rev=221233&r1=221232&r2=221233&view=diff
> ============================================================
> ==================
> --- lld/trunk/lib/ReaderWriter/ELF/OutputELFWriter.h (original)
> +++ lld/trunk/lib/ReaderWriter/ELF/OutputELFWriter.h Mon Nov  3 21:57:04
> 2014
> @@ -265,7 +265,7 @@ void OutputELFWriter<ELFT>::assignSectio
>      if (!mergedSec->hasSegment())
>        _shdrtab->appendSection(mergedSec);
>    }
> -  _layout.assignOffsetsForMiscSections();
> +  _layout.assignFileOffsetsForMiscSections();
>    for (auto sec : _layout.sections())
>      if (auto section = dyn_cast<Section<ELFT>>(sec))
>        if (!DefaultLayout<ELFT>::hasOutputSegment(section))
> @@ -377,7 +377,6 @@ std::error_code OutputELFWriter<ELFT>::b
>    // contained in them, in anyway the targets may want
>    _layout.doPreFlight();
>
> -  _layout.assignFileOffsets();
>    _layout.assignVirtualAddress();
>
>    // Finalize the default value of symbols that the linker adds
>
> Modified: lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/
> SectionChunks.h?rev=221233&r1=221232&r2=221233&view=diff
> ============================================================
> ==================
> --- lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h (original)
> +++ lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h Mon Nov  3 21:57:04
> 2014
> @@ -59,11 +59,10 @@ public:
>    virtual bool isLoadableSection() const { return false; }
>
>    /// \brief Assign file offsets starting at offset.
> -  virtual void assignOffsets(uint64_t offset) {}
> +  virtual void assignFileOffsets(uint64_t offset) {}
>
> -  /// \brief Assign virtual addresses starting at addr. Addr is modified
> to be
> -  /// the next available virtual address.
> -  virtual void assignVirtualAddress(uint64_t &addr) {}
> +  /// \brief Assign virtual addresses starting at addr.
> +  virtual void assignVirtualAddress(uint64_t addr) {}
>
>    uint64_t getFlags() const { return _flags; }
>    uint64_t getEntSize() const { return _entSize; }
> @@ -195,7 +194,7 @@ public:
>    /// \brief Set the virtual address of each Atom in the Section. This
>    /// routine gets called after the linker fixes up the virtual address
>    /// of the section
> -  virtual void assignVirtualAddress(uint64_t &addr) {
> +  virtual void assignVirtualAddress(uint64_t addr) {
>      for (auto &ai : _atoms) {
>        ai->_virtualAddr = addr + ai->_fileOffset;
>      }
> @@ -203,7 +202,7 @@ public:
>
>    /// \brief Set the file offset of each Atom in the section. This routine
>    /// gets called after the linker fixes up the section offset
> -  virtual void assignOffsets(uint64_t offset) {
> +  virtual void assignFileOffsets(uint64_t offset) {
>      for (auto &ai : _atoms) {
>        ai->_fileOffset = offset + ai->_fileOffset;
>      }
>
> Modified: lld/trunk/lib/ReaderWriter/ELF/SegmentChunks.h
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/
> SegmentChunks.h?rev=221233&r1=221232&r2=221233&view=diff
> ============================================================
> ==================
> --- lld/trunk/lib/ReaderWriter/ELF/SegmentChunks.h (original)
> +++ lld/trunk/lib/ReaderWriter/ELF/SegmentChunks.h Mon Nov  3 21:57:04
> 2014
> @@ -41,14 +41,8 @@ public:
>
>    SegmentSlice() { }
>
> -  /// Set the segment slice so that it begins at the offset specified
> -  /// by file offset and set the start of the slice to be s and the end
> -  /// of the slice to be e
> -  void set(uint64_t fileoffset, int32_t s, int e) {
> -    _startSection = s;
> -    _endSection = e + 1;
> -    _offset = fileoffset;
> -  }
> +  /// Set the start of the slice.
> +  void setStart(int32_t s) { _startSection = s; }
>
>    // Set the segment slice start and end iterators. This is used to walk
> through
>    // the sections that are part of the Segment slice
> @@ -59,8 +53,12 @@ public:
>    // Return the fileOffset of the slice
>    inline uint64_t fileOffset() const { return _offset; }
>
> +  void setFileOffset(uint64_t offset) { _offset = offset; }
> +
>    // Return the size of the slice
> -  inline uint64_t fileSize() const { return _size; }
> +  inline uint64_t fileSize() const { return _fsize; }
> +
> +  void setFileSize(uint64_t filesz) { _fsize = filesz; }
>
>    // Return the start of the slice
>    inline int32_t startSection() const { return _startSection; }
> @@ -74,11 +72,9 @@ public:
>    // Return the alignment of the slice
>    inline uint64_t align2() const { return _align2; }
>
> -  inline void setSize(uint64_t sz) { _size = sz; }
> -
>    inline void setMemSize(uint64_t memsz) { _memSize = memsz; }
>
> -  inline void setVAddr(uint64_t addr) { _addr = addr; }
> +  inline void setVirtualAddr(uint64_t addr) { _addr = addr; }
>
>    inline void setAlign(uint64_t align) { _align2 = align; }
>
> @@ -91,13 +87,12 @@ public:
>    }
>
>  private:
> -  int32_t _startSection;
> -  int32_t _endSection;
>    range<SectionIter> _sections;
> +  int32_t _startSection;
>    uint64_t _addr;
>    uint64_t _offset;
> -  uint64_t _size;
>    uint64_t _align2;
> +  uint64_t _fsize;
>    uint64_t _memSize;
>  };
>
> @@ -151,10 +146,10 @@ public:
>    /// the newly computed offset is greater than a page, then we create a
> segment
>    /// slice, as it would be a waste of virtual memory just to be filled
> with
>    /// zeroes
> -  void assignOffsets(uint64_t startOffset);
> +  void assignFileOffsets(uint64_t startOffset);
>
>    /// \brief Assign virtual addresses to the slices
> -  void assignVirtualAddress(uint64_t &addr);
> +  void assignVirtualAddress(uint64_t addr);
>
>    // Write the Segment
>    void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
> @@ -181,7 +176,7 @@ public:
>      // last section to the first section, especially for TLS because
>      // the TLS segment contains both .tdata/.tbss
>      this->setFileOffset(_sections.front()->fileOffset());
> -    this->setVAddr(_sections.front()->virtualAddr());
> +    this->setVirtualAddr(_sections.front()->virtualAddr());
>      size_t startFileOffset = _sections.front()->fileOffset();
>      size_t startAddr = _sections.front()->virtualAddr();
>      for (auto ai : _sections) {
> @@ -260,16 +255,6 @@ public:
>
>    inline range<SliceIter> slices() { return _segmentSlices; }
>
> -  // These two accessors are still needed for a call to std::stable_sort.
> -  // Consider adding wrappers for two iterator algorithms.
> -  inline SliceIter slices_begin() {
> -    return _segmentSlices.begin();
> -  }
> -
> -  inline SliceIter slices_end() {
> -    return _segmentSlices.end();
> -  }
> -
>    Chunk<ELFT> *firstSection() { return _sections[0]; }
>
>  private:
> @@ -316,7 +301,7 @@ public:
>      // section points to the ELF header and the second chunk points to the
>      // actual program headers
>      this->setFileOffset(_sections.back()->fileOffset());
> -    this->setVAddr(_sections.back()->virtualAddr());
> +    this->setVirtualAddr(_sections.back()->virtualAddr());
>      this->_fsize = _sections.back()->fileSize();
>      this->_msize = _sections.back()->memSize();
>    }
> @@ -409,58 +394,132 @@ bool Segment<ELFT>::compareSegments(Segm
>    return false;
>  }
>
> -template <class ELFT> void Segment<ELFT>::assignOffsets(uint64_t
> startOffset) {
> +template <class ELFT>
> +void Segment<ELFT>::assignFileOffsets(uint64_t startOffset) {
> +  uint64_t fileOffset = startOffset;
> +  uint64_t curSliceFileOffset = fileOffset;
> +  bool isDataPageAlignedForNMagic = false;
> +
> +  this->setFileOffset(startOffset);
> +  for (auto &slice : slices()) {
> +    // Align to the slice alignment
> +    fileOffset = llvm::RoundUpToAlignment(fileOffset, slice->align2());
> +
> +    bool isFirstSection = true;
> +
> +    for (auto section : slice->sections()) {
> +      // If the linker outputmagic is set to OutputMagic::NMAGIC, align
> the Data
> +      // to a page boundary
> +      if (isFirstSection &&
> +          _outputMagic != ELFLinkingContext::OutputMagic::NMAGIC &&
> +          _outputMagic != ELFLinkingContext::OutputMagic::OMAGIC) {
> +        // Align to a page only if the output is not
> +        // OutputMagic::NMAGIC/OutputMagic::OMAGIC
> +        fileOffset =
> +            llvm::RoundUpToAlignment(fileOffset,
> this->_context.getPageSize());
> +      }
> +      if (!isDataPageAlignedForNMagic && needAlign(section)) {
> +        fileOffset =
> +            llvm::RoundUpToAlignment(fileOffset,
> this->_context.getPageSize());
> +        isDataPageAlignedForNMagic = true;
> +      }
> +      // Align the section address
> +      fileOffset = llvm::RoundUpToAlignment(fileOffset,
> section->align2());
> +
> +      if (isFirstSection) {
> +        slice->setFileOffset(fileOffset);
> +        isFirstSection = false;
> +        curSliceFileOffset = fileOffset;
> +      }
> +      section->setFileOffset(fileOffset);
> +      fileOffset += section->fileSize();
> +    }
> +    slice->setFileSize(fileOffset - curSliceFileOffset);
> +  }
> +  this->setFileSize(fileOffset - startOffset);
> +}
> +
> +/// \brief Assign virtual addresses to the slices
> +template <class ELFT> void Segment<ELFT>::assignVirtualAddress(uint64_t
> addr) {
>    int startSection = 0;
>    int currSection = 0;
> -  SectionIter startSectionIter, endSectionIter;
> +  SectionIter startSectionIter;
> +
>    // slice align is set to the max alignment of the chunks that are
>    // contained in the slice
>    uint64_t sliceAlign = 0;
>    // Current slice size
>    uint64_t curSliceSize = 0;
>    // Current Slice File Offset
> -  uint64_t curSliceFileOffset = 0;
> +  uint64_t curSliceAddress = 0;
>
>    startSectionIter = _sections.begin();
> -  endSectionIter = _sections.end();
>    startSection = 0;
>    bool isFirstSection = true;
>    bool isDataPageAlignedForNMagic = false;
> +  uint64_t startAddr = addr;
> +  SegmentSlice<ELFT> *slice = nullptr;
> +  uint64_t tlsStartAddr = 0;
> +
>    for (auto si = _sections.begin(); si != _sections.end(); ++si) {
> +    // If this is first section in the segment, page align the section
> start
> +    // address. The linker needs to align the data section to a page
> boundary
> +    // only if NMAGIC is set.
>      if (isFirstSection) {
> -      // If the linker outputmagic is set to OutputMagic::NMAGIC, align
> the Data
> -      // to a page boundary
> -      if (!isDataPageAlignedForNMagic && needAlign(*si)) {
> -        startOffset =
> -            llvm::RoundUpToAlignment(startOffset,
> this->_context.getPageSize());
> +      isFirstSection = false;
> +      if (_outputMagic != ELFLinkingContext::OutputMagic::NMAGIC &&
> +          _outputMagic != ELFLinkingContext::OutputMagic::OMAGIC)
> +        // Align to a page only if the output is not
> +        // OutputMagic::NMAGIC/OutputMagic::OMAGIC
> +        startAddr =
> +            llvm::RoundUpToAlignment(startAddr,
> this->_context.getPageSize());
> +      else if (!isDataPageAlignedForNMagic && needAlign(*si)) {
> +        // If the linker outputmagic is set to OutputMagic::NMAGIC, align
> the
> +        // Data to a page boundary.
> +        startAddr =
> +            llvm::RoundUpToAlignment(startAddr,
> this->_context.getPageSize());
>          isDataPageAlignedForNMagic = true;
>        }
>        // align the startOffset to the section alignment
> -      uint64_t newOffset =
> -        llvm::RoundUpToAlignment(startOffset, (*si)->align2());
> -      curSliceFileOffset = newOffset;
> +      uint64_t newAddr = llvm::RoundUpToAlignment(startAddr,
> (*si)->align2());
> +      curSliceAddress = newAddr;
>        sliceAlign = (*si)->align2();
> -      this->setFileOffset(startOffset);
> -      (*si)->setFileOffset(newOffset);
> -      curSliceSize = (*si)->fileSize();
> -      isFirstSection = false;
> +      (*si)->setVirtualAddr(curSliceAddress);
> +
> +      // Handle TLS.
> +      if (auto section = dyn_cast<AtomSection<ELFT>>(*si)) {
> +        if (section->getSegmentType() == llvm::ELF::PT_TLS) {
> +          tlsStartAddr =
> +              llvm::RoundUpToAlignment(tlsStartAddr, (*si)->align2());
> +          section->assignVirtualAddress(tlsStartAddr);
> +          tlsStartAddr += (*si)->memSize();
> +        } else {
> +          section->assignVirtualAddress(newAddr);
> +        }
> +      }
> +      // TBSS section is special in that it doesn't contribute to memory
> of any
> +      // segment. If we see a tbss section, don't add memory size to addr
> The
> +      // fileOffset is automatically taken care of since TBSS section
> does not
> +      // end up using file size
> +      if ((*si)->order() != DefaultLayout<ELFT>::ORDER_TBSS)
> +        curSliceSize = (*si)->memSize();
>      } else {
> -      uint64_t curOffset = curSliceFileOffset + curSliceSize;
> -      // If the linker outputmagic is set to OutputMagic::NMAGIC, align
> the Data
> -      // to a page boundary
> +      uint64_t curAddr = curSliceAddress + curSliceSize;
>        if (!isDataPageAlignedForNMagic && needAlign(*si)) {
> -        curOffset =
> -            llvm::RoundUpToAlignment(curOffset,
> this->_context.getPageSize());
> +        // If the linker outputmagic is set to OutputMagic::NMAGIC, align
> the
> +        // Data
> +        // to a page boundary
> +        curAddr =
> +            llvm::RoundUpToAlignment(curAddr,
> this->_context.getPageSize());
>          isDataPageAlignedForNMagic = true;
>        }
> -      uint64_t newOffset = llvm::RoundUpToAlignment(curOffset,
> (*si)->align2());
> -      SegmentSlice<ELFT> *slice = nullptr;
> -      // If the newOffset computed is more than a page away, let's create
> +      uint64_t newAddr = llvm::RoundUpToAlignment(curAddr,
> (*si)->align2());
> +      // If the newAddress computed is more than a page away, let's create
>        // a separate segment, so that memory is not used up while running
> -      if (((newOffset - curOffset) > this->_context.getPageSize()) &&
> +      if (((newAddr - curAddr) > this->_context.getPageSize()) &&
>            (_outputMagic != ELFLinkingContext::OutputMagic::NMAGIC &&
>             _outputMagic != ELFLinkingContext::OutputMagic::OMAGIC)) {
> -
> +        slice = nullptr;
>          // TODO: use std::find here
>          for (auto s : slices()) {
>            if (s->startSection() == startSection) {
> @@ -473,30 +532,48 @@ template <class ELFT> void Segment<ELFT>
>              SegmentSlice<ELFT>();
>            _segmentSlices.push_back(slice);
>          }
> -        slice->set(curSliceFileOffset, startSection, currSection);
> -        slice->setSections(make_range(startSectionIter, endSectionIter));
> -        slice->setSize(curSliceSize);
> +        slice->setStart(startSection);
> +        slice->setSections(make_range(startSectionIter, si));
> +        slice->setMemSize(curSliceSize);
>          slice->setAlign(sliceAlign);
> -        uint64_t newPageOffset =
> -            llvm::RoundUpToAlignment(curOffset,
> this->_context.getPageSize());
> -        newOffset = llvm::RoundUpToAlignment(newPageOffset,
> (*si)->align2());
> -        curSliceFileOffset = newOffset;
> -        startSectionIter = endSectionIter;
> +        slice->setVirtualAddr(curSliceAddress);
> +        // Start new slice
> +        curSliceAddress = newAddr;
> +        (*si)->setVirtualAddr(curSliceAddress);
> +        startSectionIter = si;
>          startSection = currSection;
> -        (*si)->setFileOffset(curSliceFileOffset);
> -        curSliceSize = newOffset - curSliceFileOffset + (*si)->fileSize();
> +        if (auto section = dyn_cast<AtomSection<ELFT>>(*si))
> +          section->assignVirtualAddress(newAddr);
> +        curSliceSize = newAddr - curSliceAddress + (*si)->memSize();
>          sliceAlign = (*si)->align2();
>        } else {
>          if (sliceAlign < (*si)->align2())
>            sliceAlign = (*si)->align2();
> -        (*si)->setFileOffset(newOffset);
> -        curSliceSize = newOffset - curSliceFileOffset + (*si)->fileSize();
> +        (*si)->setVirtualAddr(newAddr);
> +        // Handle TLS.
> +        if (auto section = dyn_cast<AtomSection<ELFT>>(*si)) {
> +          if (section->getSegmentType() == llvm::ELF::PT_TLS) {
> +            tlsStartAddr =
> +                llvm::RoundUpToAlignment(tlsStartAddr, (*si)->align2());
> +            section->assignVirtualAddress(tlsStartAddr);
> +            tlsStartAddr += (*si)->memSize();
> +          } else {
> +            section->assignVirtualAddress(newAddr);
> +          }
> +        }
> +        // TBSS section is special in that it doesn't contribute to
> memory of
> +        // any segment. If we see a tbss section, don't add memory size
> to addr
> +        // The fileOffset is automatically taken care of since TBSS
> section does
> +        // not end up using file size.
> +        if ((*si)->order() != DefaultLayout<ELFT>::ORDER_TBSS)
> +          curSliceSize = newAddr - curSliceAddress + (*si)->memSize();
> +        else
> +          curSliceSize = newAddr - curSliceAddress;
>        }
>      }
>      currSection++;
> -    endSectionIter = si;
>    }
> -  SegmentSlice<ELFT> *slice = nullptr;
> +  slice = nullptr;
>    for (auto s : slices()) {
>      // TODO: add std::find
>      if (s->startSection() == startSection) {
> @@ -509,74 +586,17 @@ template <class ELFT> void Segment<ELFT>
>        SegmentSlice<ELFT>();
>      _segmentSlices.push_back(slice);
>    }
> -  slice->set(curSliceFileOffset, startSection, currSection);
> +  slice->setStart(startSection);
> +  slice->setVirtualAddr(curSliceAddress);
> +  slice->setMemSize(curSliceSize);
>    slice->setSections(make_range(startSectionIter, _sections.end()));
> -  slice->setSize(curSliceSize);
>    slice->setAlign(sliceAlign);
> -  this->_fsize = curSliceFileOffset - startOffset + curSliceSize;
> -  std::stable_sort(slices_begin(), slices_end(),
> -                   SegmentSlice<ELFT>::compare_slices);
> -}
>
> -/// \brief Assign virtual addresses to the slices
> -template <class ELFT> void Segment<ELFT>::assignVirtualAddress(uint64_t
> &addr) {
> -  bool isTLSSegment = false;
> -  bool isDataPageAlignedForNMagic = false;
> -  uint64_t tlsStartAddr = 0;
> -
> -  for (auto slice : slices()) {
> -    // Align to a page only if the output is not
> -    // OutputMagic::NMAGIC/OutputMagic::OMAGIC
> -    if (_outputMagic != ELFLinkingContext::OutputMagic::NMAGIC &&
> -        _outputMagic != ELFLinkingContext::OutputMagic::OMAGIC)
> -      addr = llvm::RoundUpToAlignment(addr, this->_context.getPageSize());
> -
> -    // Align to the slice alignment
> -    addr = llvm::RoundUpToAlignment(addr, slice->align2());
> -
> -    bool virtualAddressSet = false;
> -    for (auto section : slice->sections()) {
> -      // If the linker outputmagic is set to OutputMagic::NMAGIC, align
> the Data
> -      // to a page boundary
> -      if (!isDataPageAlignedForNMagic && needAlign(section)) {
> -        addr = llvm::RoundUpToAlignment(addr,
> this->_context.getPageSize());
> -        isDataPageAlignedForNMagic = true;
> -      }
> -      // Align the section address
> -      addr = llvm::RoundUpToAlignment(addr, section->align2());
> -      // Check if the segment is of type TLS
> -      // The sections that belong to the TLS segment have their
> -      // virtual addresses that are relative To TP
> -      Section<ELFT> *currentSection = dyn_cast<Section<ELFT> >(section);
> -      if (currentSection)
> -        isTLSSegment = (currentSection->getSegmentType() ==
> llvm::ELF::PT_TLS);
> -
> -      tlsStartAddr = (isTLSSegment)
> -                     ? llvm::RoundUpToAlignment(tlsStartAddr,
> section->align2())
> -                     : 0;
> -      if (!virtualAddressSet) {
> -        slice->setVAddr(addr);
> -        virtualAddressSet = true;
> -      }
> -      section->setVAddr(addr);
> -      if (auto s = dyn_cast<Section<ELFT> >(section)) {
> -        if (isTLSSegment)
> -          s->assignVirtualAddress(tlsStartAddr);
> -        else
> -          s->assignVirtualAddress(addr);
> -      }
> -      if (isTLSSegment)
> -        tlsStartAddr += section->memSize();
> -      section->setMemSize(addr + section->memSize() -
> section->virtualAddr());
> -      // TBSS section is special in that it doesn't contribute to memory
> of any
> -      // segment. If we see a tbss section, don't add memory size to addr
> -      // The fileOffset is automatically taken care of since TBSS section
> does
> -      // not end up using file size
> -      if (section->order() != DefaultLayout<ELFT>::ORDER_TBSS)
> -        addr += section->memSize();
> -    }
> -    slice->setMemSize(addr - slice->virtualAddr());
> -  }
> +  // Set the segment memory size and the virtual address.
> +  this->setMemSize(curSliceAddress - startAddr + curSliceSize);
> +  this->setVirtualAddr(curSliceAddress);
> +  std::stable_sort(_segmentSlices.begin(), _segmentSlices.end(),
> +                   SegmentSlice<ELFT>::compare_slices);
>  }
>
>  // Write the Segment
>
> Modified: lld/trunk/test/elf/phdr.test
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/
> phdr.test?rev=221233&r1=221232&r2=221233&view=diff
> ============================================================
> ==================
> --- lld/trunk/test/elf/phdr.test (original)
> +++ lld/trunk/test/elf/phdr.test Mon Nov  3 21:57:04 2014
> @@ -50,7 +50,7 @@ I386-NEXT:     Offset: 0x1000
>  I386-NEXT:     VirtualAddress: 0x1000
>  I386-NEXT:     PhysicalAddress: 0x1000
>  I386-NEXT:     FileSize: 260
> -I386-NEXT:     MemSize: 4
> +I386-NEXT:     MemSize: 260
>  I386-NEXT:     Flags [ (0x6)
>  I386-NEXT:       PF_R (0x4)
>  I386-NEXT:       PF_W (0x2)
> @@ -63,7 +63,7 @@ I386-NEXT:     Offset: 0x4000
>  I386-NEXT:     VirtualAddress: 0x4000
>  I386-NEXT:     PhysicalAddress: 0x4000
>  I386-NEXT:     FileSize: 4
> -I386-NEXT:     MemSize: 16392
> +I386-NEXT:     MemSize: 8
>  I386-NEXT:     Flags [ (0x6)
>  I386-NEXT:       PF_R (0x4)
>  I386-NEXT:       PF_W (0x2)
>
>
> _______________________________________________
> llvm-commits mailing listllvm-commits at cs.uiuc.eduhttp://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
>
>
> _______________________________________________
> llvm-commits mailing listllvm-commits at cs.uiuc.eduhttp://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
>
>
> --
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by the Linux Foundation
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20141104/f4846f26/attachment.html>


More information about the llvm-commits mailing list