[lld] r221233 - [ELF] Fix program headers.
Eric Christopher
echristo at gmail.com
Tue Nov 4 15:17:41 PST 2014
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
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20141104/f4846f26/attachment.html>
More information about the llvm-commits
mailing list