summaryrefslogtreecommitdiffstats
path: root/lld/lib/ReaderWriter/ELF/SegmentChunks.cpp
diff options
context:
space:
mode:
authorRui Ueyama <ruiu@google.com>2015-04-14 21:20:37 +0000
committerRui Ueyama <ruiu@google.com>2015-04-14 21:20:37 +0000
commit5ec40d6e7398d7ddbffccc0bf635554d0ae252d1 (patch)
tree9115dd2b65d8126549cef54b7e5b0ea32d4657c6 /lld/lib/ReaderWriter/ELF/SegmentChunks.cpp
parentb60453fe2975d7b3b7cf764ffa48b7cbedd4f47e (diff)
downloadbcm5719-llvm-5ec40d6e7398d7ddbffccc0bf635554d0ae252d1.tar.gz
bcm5719-llvm-5ec40d6e7398d7ddbffccc0bf635554d0ae252d1.zip
ELF: Attempt to simplify Segment::assignVirtualAddress().
This function is too long and complicated. Looks like new code was added incrementaly without any refactoring. Maybe no one can describe its exact semantics any more? It even contains copy-pastes inside it. This patch is an (incomplete) attempt to simplify the function. I tried to mechanically translate code to another form more intelligible. I don't still understand the whole picture, but this patch shouldn't change the linker's functionality. llvm-svn: 234944
Diffstat (limited to 'lld/lib/ReaderWriter/ELF/SegmentChunks.cpp')
-rw-r--r--lld/lib/ReaderWriter/ELF/SegmentChunks.cpp228
1 files changed, 105 insertions, 123 deletions
diff --git a/lld/lib/ReaderWriter/ELF/SegmentChunks.cpp b/lld/lib/ReaderWriter/ELF/SegmentChunks.cpp
index 237ef059ebf..b915f1ee647 100644
--- a/lld/lib/ReaderWriter/ELF/SegmentChunks.cpp
+++ b/lld/lib/ReaderWriter/ELF/SegmentChunks.cpp
@@ -175,158 +175,140 @@ template <class ELFT> void Segment<ELFT>::assignVirtualAddress(uint64_t addr) {
// 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 curSliceAddress = 0;
startSectionIter = _sections.begin();
startSection = 0;
- bool isFirstSection = true;
- bool isDataPageAlignedForNMagic = false;
uint64_t startAddr = addr;
SegmentSlice<ELFT> *slice = nullptr;
uint64_t tlsStartAddr = 0;
- bool alignSegments = this->_ctx.alignSegments();
StringRef prevOutputSectionName = StringRef();
- for (auto si = _sections.begin(); si != _sections.end(); ++si) {
+ auto si = _sections.begin();
+ if (si != _sections.end()) {
// 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) {
- isFirstSection = false;
- if (alignSegments &&
- _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->_ctx.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->_ctx.getPageSize());
- isDataPageAlignedForNMagic = true;
+ if (needAlign(*si) ||
+ (this->_ctx.alignSegments() &&
+ _outputMagic != ELFLinkingContext::OutputMagic::NMAGIC &&
+ _outputMagic != ELFLinkingContext::OutputMagic::OMAGIC)) {
+ startAddr = llvm::RoundUpToAlignment(startAddr, this->_ctx.getPageSize());
+ }
+ // align the startOffset to the section alignment
+ uint64_t newAddr = llvm::RoundUpToAlignment(startAddr, (*si)->alignment());
+ // Handle linker script expressions, which *may update newAddr* if the
+ // expression assigns to "."
+ if (auto expr = dyn_cast<ExpressionChunk<ELFT>>(*si))
+ expr->evalExpr(newAddr);
+ curSliceAddress = newAddr;
+ sliceAlign = (*si)->alignment();
+ (*si)->setVirtualAddr(curSliceAddress);
+
+ // Handle TLS.
+ if (auto section = dyn_cast<Section<ELFT>>(*si)) {
+ if (section->getSegmentType() == llvm::ELF::PT_TLS) {
+ tlsStartAddr =
+ llvm::RoundUpToAlignment(tlsStartAddr, (*si)->alignment());
+ 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() != TargetLayout<ELFT>::ORDER_TBSS)
+ curSliceSize = (*si)->memSize();
+ }
+ ++currSection;
+ ++si;
+
+ for (auto e = _sections.end(); si != e; ++si) {
+ uint64_t curAddr = curSliceAddress + curSliceSize;
+ uint64_t newAddr = llvm::RoundUpToAlignment(curAddr, (*si)->alignment());
+ // Handle linker script expressions, which *may update newAddr* if the
+ // expression assigns to "."
+ if (auto expr = dyn_cast<ExpressionChunk<ELFT>>(*si))
+ expr->evalExpr(newAddr);
+ Section<ELFT> *sec = dyn_cast<Section<ELFT>>(*si);
+ StringRef curOutputSectionName;
+ if (sec) {
+ curOutputSectionName = sec->outputSectionName();
+ } else {
+ // If this is a linker script expression, propagate the name of the
+ // previous section instead
+ if (isa<ExpressionChunk<ELFT>>(*si))
+ curOutputSectionName = prevOutputSectionName;
+ else
+ curOutputSectionName = (*si)->name();
+ }
+ bool autoCreateSlice = true;
+ if (curOutputSectionName == prevOutputSectionName)
+ autoCreateSlice = false;
+ // 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.
+ // Dont create a slice, if the new section falls in the same output
+ // section as the previous section.
+ if (autoCreateSlice && ((newAddr - curAddr) > this->_ctx.getPageSize()) &&
+ (_outputMagic != ELFLinkingContext::OutputMagic::NMAGIC &&
+ _outputMagic != ELFLinkingContext::OutputMagic::OMAGIC)) {
+ auto sliceIter =
+ std::find_if(_segmentSlices.begin(), _segmentSlices.end(),
+ [startSection](SegmentSlice<ELFT> *s) -> bool {
+ return s->startSection() == startSection;
+ });
+ if (sliceIter == _segmentSlices.end()) {
+ slice = new (_segmentAllocate.Allocate<SegmentSlice<ELFT>>())
+ SegmentSlice<ELFT>();
+ _segmentSlices.push_back(slice);
+ } else {
+ slice = *sliceIter;
}
- // align the startOffset to the section alignment
- uint64_t newAddr =
- llvm::RoundUpToAlignment(startAddr, (*si)->alignment());
- // Handle linker script expressions, which *may update newAddr* if the
- // expression assigns to "."
- if (auto expr = dyn_cast<ExpressionChunk<ELFT>>(*si))
- expr->evalExpr(newAddr);
+ slice->setStart(startSection);
+ slice->setSections(make_range(startSectionIter, si));
+ slice->setMemSize(curSliceSize);
+ slice->setAlign(sliceAlign);
+ slice->setVirtualAddr(curSliceAddress);
+ // Start new slice
curSliceAddress = newAddr;
- sliceAlign = (*si)->alignment();
(*si)->setVirtualAddr(curSliceAddress);
-
+ startSectionIter = si;
+ startSection = currSection;
+ if (auto section = dyn_cast<Section<ELFT>>(*si))
+ section->assignVirtualAddress(newAddr);
+ curSliceSize = newAddr - curSliceAddress + (*si)->memSize();
+ sliceAlign = (*si)->alignment();
+ } else {
+ if (sliceAlign < (*si)->alignment())
+ sliceAlign = (*si)->alignment();
+ (*si)->setVirtualAddr(newAddr);
// Handle TLS.
if (auto section = dyn_cast<Section<ELFT>>(*si)) {
if (section->getSegmentType() == llvm::ELF::PT_TLS) {
tlsStartAddr =
- llvm::RoundUpToAlignment(tlsStartAddr, (*si)->alignment());
+ llvm::RoundUpToAlignment(tlsStartAddr, (*si)->alignment());
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() != TargetLayout<ELFT>::ORDER_TBSS)
- curSliceSize = (*si)->memSize();
- } else {
- uint64_t curAddr = curSliceAddress + curSliceSize;
- if (!isDataPageAlignedForNMagic && needAlign(*si)) {
- // If the linker outputmagic is set to OutputMagic::NMAGIC, align the
- // Data
- // to a page boundary
- curAddr = llvm::RoundUpToAlignment(curAddr, this->_ctx.getPageSize());
- isDataPageAlignedForNMagic = true;
- }
- uint64_t newAddr = llvm::RoundUpToAlignment(curAddr, (*si)->alignment());
- // Handle linker script expressions, which *may update newAddr* if the
- // expression assigns to "."
- if (auto expr = dyn_cast<ExpressionChunk<ELFT>>(*si))
- expr->evalExpr(newAddr);
- Section<ELFT> *sec = dyn_cast<Section<ELFT>>(*si);
- StringRef curOutputSectionName;
- if (sec)
- curOutputSectionName = sec->outputSectionName();
- else {
- // If this is a linker script expression, propagate the name of the
- // previous section instead
- if (isa<ExpressionChunk<ELFT>>(*si))
- curOutputSectionName = prevOutputSectionName;
- else
- curOutputSectionName = (*si)->name();
- }
- bool autoCreateSlice = true;
- if (curOutputSectionName == prevOutputSectionName)
- autoCreateSlice = false;
- // 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.
- // Dont create a slice, if the new section falls in the same output
- // section as the previous section.
- if (autoCreateSlice && ((newAddr - curAddr) > this->_ctx.getPageSize()) &&
- (_outputMagic != ELFLinkingContext::OutputMagic::NMAGIC &&
- _outputMagic != ELFLinkingContext::OutputMagic::OMAGIC)) {
- auto sliceIter =
- std::find_if(_segmentSlices.begin(), _segmentSlices.end(),
- [startSection](SegmentSlice<ELFT> *s) -> bool {
- return s->startSection() == startSection;
- });
- if (sliceIter == _segmentSlices.end()) {
- slice = new (_segmentAllocate.Allocate<SegmentSlice<ELFT>>())
- SegmentSlice<ELFT>();
- _segmentSlices.push_back(slice);
- } else {
- slice = (*sliceIter);
- }
- slice->setStart(startSection);
- slice->setSections(make_range(startSectionIter, si));
- slice->setMemSize(curSliceSize);
- slice->setAlign(sliceAlign);
- slice->setVirtualAddr(curSliceAddress);
- // Start new slice
- curSliceAddress = newAddr;
- (*si)->setVirtualAddr(curSliceAddress);
- startSectionIter = si;
- startSection = currSection;
- if (auto section = dyn_cast<Section<ELFT>>(*si))
- 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() != TargetLayout<ELFT>::ORDER_TBSS) {
curSliceSize = newAddr - curSliceAddress + (*si)->memSize();
- sliceAlign = (*si)->alignment();
} else {
- if (sliceAlign < (*si)->alignment())
- sliceAlign = (*si)->alignment();
- (*si)->setVirtualAddr(newAddr);
- // Handle TLS.
- if (auto section = dyn_cast<Section<ELFT>>(*si)) {
- if (section->getSegmentType() == llvm::ELF::PT_TLS) {
- tlsStartAddr =
- llvm::RoundUpToAlignment(tlsStartAddr, (*si)->alignment());
- 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() != TargetLayout<ELFT>::ORDER_TBSS)
- curSliceSize = newAddr - curSliceAddress + (*si)->memSize();
- else
- curSliceSize = newAddr - curSliceAddress;
+ curSliceSize = newAddr - curSliceAddress;
}
- prevOutputSectionName = curOutputSectionName;
}
- currSection++;
+ prevOutputSectionName = curOutputSectionName;
+ ++currSection;
}
auto sliceIter = std::find_if(_segmentSlices.begin(), _segmentSlices.end(),
[startSection](SegmentSlice<ELFT> *s) -> bool {
@@ -337,7 +319,7 @@ template <class ELFT> void Segment<ELFT>::assignVirtualAddress(uint64_t addr) {
SegmentSlice<ELFT>();
_segmentSlices.push_back(slice);
} else {
- slice = (*sliceIter);
+ slice = *sliceIter;
}
slice->setStart(startSection);
slice->setVirtualAddr(curSliceAddress);
OpenPOWER on IntegriCloud