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