[lld] r234944 - ELF: Attempt to simplify Segment::assignVirtualAddress().

Rui Ueyama ruiu at google.com
Tue Apr 14 14:20:38 PDT 2015


Author: ruiu
Date: Tue Apr 14 16:20:37 2015
New Revision: 234944

URL: http://llvm.org/viewvc/llvm-project?rev=234944&view=rev
Log:
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.

Modified:
    lld/trunk/lib/ReaderWriter/ELF/SegmentChunks.cpp

Modified: lld/trunk/lib/ReaderWriter/ELF/SegmentChunks.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/SegmentChunks.cpp?rev=234944&r1=234943&r2=234944&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/SegmentChunks.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/SegmentChunks.cpp Tue Apr 14 16:20:37 2015
@@ -175,158 +175,140 @@ template <class ELFT> void Segment<ELFT>
   // 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>
         SegmentSlice<ELFT>();
     _segmentSlices.push_back(slice);
   } else {
-    slice = (*sliceIter);
+    slice = *sliceIter;
   }
   slice->setStart(startSection);
   slice->setVirtualAddr(curSliceAddress);





More information about the llvm-commits mailing list