[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