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

Shankar Easwaran shankare at codeaurora.org
Tue Nov 4 15:15:45 PST 2014


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>
> 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 list
>> llvm-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>>
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://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/042d8f71/attachment.html>


More information about the llvm-commits mailing list