summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/lib/ReaderWriter/ELF/Chunk.h11
-rw-r--r--lld/lib/ReaderWriter/ELF/DefaultLayout.h76
-rw-r--r--lld/lib/ReaderWriter/ELF/HeaderChunks.h8
-rw-r--r--lld/lib/ReaderWriter/ELF/Layout.h2
-rw-r--r--lld/lib/ReaderWriter/ELF/OutputELFWriter.h3
-rw-r--r--lld/lib/ReaderWriter/ELF/SectionChunks.h11
-rw-r--r--lld/lib/ReaderWriter/ELF/SegmentChunks.h288
-rw-r--r--lld/test/elf/phdr.test4
8 files changed, 191 insertions, 212 deletions
diff --git a/lld/lib/ReaderWriter/ELF/Chunk.h b/lld/lib/ReaderWriter/ELF/Chunk.h
index 8bf66d3b960..4e495811028 100644
--- a/lld/lib/ReaderWriter/ELF/Chunk.h
+++ b/lld/lib/ReaderWriter/ELF/Chunk.h
@@ -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; }
diff --git a/lld/lib/ReaderWriter/ELF/DefaultLayout.h b/lld/lib/ReaderWriter/ELF/DefaultLayout.h
index 2cfba915a13..57b28e4d550 100644
--- a/lld/lib/ReaderWriter/ELF/DefaultLayout.h
+++ b/lld/lib/ReaderWriter/ELF/DefaultLayout.h
@@ -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<ELFT>::assignSectionsToSegments() {
}
}
-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>::assignVirtualAddress() {
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>::assignVirtualAddress() {
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>::assignVirtualAddress() {
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>::assignVirtualAddress() {
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>::assignVirtualAddress() {
}
}
-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>::assignOffsetsForMiscSections() {
continue;
fileoffset = llvm::RoundUpToAlignment(fileoffset, si->align2());
si->setFileOffset(fileoffset);
- si->setVAddr(0);
+ si->setVirtualAddr(0);
fileoffset += si->fileSize();
}
}
diff --git a/lld/lib/ReaderWriter/ELF/HeaderChunks.h b/lld/lib/ReaderWriter/ELF/HeaderChunks.h
index b32ef6c7d33..5a83ee56b50 100644
--- a/lld/lib/ReaderWriter/ELF/HeaderChunks.h
+++ b/lld/lib/ReaderWriter/ELF/HeaderChunks.h
@@ -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);
diff --git a/lld/lib/ReaderWriter/ELF/Layout.h b/lld/lib/ReaderWriter/ELF/Layout.h
index 4fb97140749..bb8cffe701d 100644
--- a/lld/lib/ReaderWriter/ELF/Layout.h
+++ b/lld/lib/ReaderWriter/ELF/Layout.h
@@ -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() {}
diff --git a/lld/lib/ReaderWriter/ELF/OutputELFWriter.h b/lld/lib/ReaderWriter/ELF/OutputELFWriter.h
index 9eab2cfcabc..7eb9bd9500a 100644
--- a/lld/lib/ReaderWriter/ELF/OutputELFWriter.h
+++ b/lld/lib/ReaderWriter/ELF/OutputELFWriter.h
@@ -265,7 +265,7 @@ void OutputELFWriter<ELFT>::assignSectionsWithNoSegments() {
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>::buildOutput(const File &file) {
// 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
diff --git a/lld/lib/ReaderWriter/ELF/SectionChunks.h b/lld/lib/ReaderWriter/ELF/SectionChunks.h
index 026b78dd37d..244382eb09d 100644
--- a/lld/lib/ReaderWriter/ELF/SectionChunks.h
+++ b/lld/lib/ReaderWriter/ELF/SectionChunks.h
@@ -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;
}
diff --git a/lld/lib/ReaderWriter/ELF/SegmentChunks.h b/lld/lib/ReaderWriter/ELF/SegmentChunks.h
index c9be23517ac..0f07e7d504e 100644
--- a/lld/lib/ReaderWriter/ELF/SegmentChunks.h
+++ b/lld/lib/ReaderWriter/ELF/SegmentChunks.h
@@ -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(Segment<ELFT> *sega, Segment<ELFT> *segb) {
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>::assignOffsets(uint64_t startOffset) {
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>::assignOffsets(uint64_t startOffset) {
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
diff --git a/lld/test/elf/phdr.test b/lld/test/elf/phdr.test
index 9122bd0dd58..3f626aa1179 100644
--- a/lld/test/elf/phdr.test
+++ b/lld/test/elf/phdr.test
@@ -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)
OpenPOWER on IntegriCloud