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

Shankar Easwaran shankare at codeaurora.org
Tue Nov 4 16:00:41 PST 2014


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




More information about the llvm-commits mailing list