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

Rui Ueyama ruiu at google.com
Tue Nov 4 16:22:17 PST 2014


I pointed out the same thing recently as a post-commit review for r220129.
You can almost always separate cleanup patches from actual changes, so
please do that. Small patches are always better.

On Tue, Nov 4, 2014 at 4:00 PM, Shankar Easwaran <shankare at codeaurora.org>
wrote:

> Thinking about this, the cleanup part of the change could have been done
> separately. Will try to take care of this for all future patches.
>
> Shankar Easwaran
>
> On 11/4/2014 5:17 PM, Eric Christopher wrote:
>
>> 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
>>>
>>>
>>>
>
> --
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted
> by the Linux Foundation
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20141104/afcf7509/attachment.html>


More information about the llvm-commits mailing list