[lld] r328810 - Refactor Writer::checkNoOverlappingSections. NFC.

Rui Ueyama via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 29 11:24:02 PDT 2018


Author: ruiu
Date: Thu Mar 29 11:24:01 2018
New Revision: 328810

URL: http://llvm.org/viewvc/llvm-project?rev=328810&view=rev
Log:
Refactor Writer::checkNoOverlappingSections. NFC.

This patch rewrites the function to remove lambda callbacks and use
of template. The algorithm is the same as before.

Modified:
    lld/trunk/ELF/Writer.cpp

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=328810&r1=328809&r2=328810&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Thu Mar 29 11:24:01 2018
@@ -62,7 +62,7 @@ private:
   void assignFileOffsets();
   void assignFileOffsetsBinary();
   void setPhdrs();
-  void checkNoOverlappingSections();
+  void checkSectionOverlap();
   void fixSectionAlignments();
   void openFile();
   void writeTrapInstr();
@@ -458,7 +458,7 @@ template <class ELFT> void Writer<ELFT>:
   }
 
   if (Config->CheckSections)
-    checkNoOverlappingSections();
+    checkSectionOverlap();
 
   // It does not make sense try to open the file if we have error already.
   if (errorCount())
@@ -1966,23 +1966,19 @@ template <class ELFT> void Writer<ELFT>:
   }
 }
 
+// A helper struct for checkSectionOverlap.
+namespace {
+struct SectionOffset {
+  OutputSection *Sec;
+  uint64_t Offset;
+};
+} // namespace
+
 // Check whether sections overlap for a specific address range (file offsets,
 // load and virtual adresses).
 //
-// This is a helper function called by Writer::checkNoOverlappingSections().
-template <typename Getter, typename Predicate>
-static void checkForSectionOverlap(ArrayRef<OutputSection *> AllSections,
-                                   StringRef Kind, Getter GetStart,
-                                   Predicate ShouldSkip) {
-  std::vector<OutputSection *> Sections;
-  // By removing all zero-size sections we can simplify the check for overlap to
-  // just checking whether the section range contains the other section's start
-  // address. Additionally, it also slightly speeds up the checking since we
-  // don't bother checking for overlap with sections that can never overlap.
-  for (OutputSection *Sec : AllSections)
-    if (Sec->Size > 0 && !ShouldSkip(Sec))
-      Sections.push_back(Sec);
-
+// This is a helper function called by Writer::checkSectionOverlap().
+static void checkOverlap(StringRef Name, std::vector<SectionOffset> &Sections) {
   // Instead of comparing every OutputSection with every other output section
   // we sort the sections by address (file offset or load/virtual address). This
   // way we find all overlapping sections but only need one comparision with the
@@ -1990,24 +1986,29 @@ static void checkForSectionOverlap(Array
   // doing more than one iteration of the following nested loop is if there are
   // overlapping sections.
   std::sort(Sections.begin(), Sections.end(),
-            [=](const OutputSection *A, const OutputSection *B) {
-              return GetStart(A) < GetStart(B);
+            [=](const SectionOffset &A, const SectionOffset &B) {
+              return A.Offset < B.Offset;
             });
+
+  // Since the sections are sorted by start address we only need to check
+  // whether the other sections starts before the end of Sec. If this is
+  // not the case we can break out of this loop since all following sections
+  // will also start after the end of Sec.
   for (size_t I = 0; I < Sections.size(); ++I) {
-    OutputSection *Sec = Sections[I];
-    uint64_t Start = GetStart(Sec);
-    for (auto *Other : ArrayRef<OutputSection *>(Sections).slice(I + 1)) {
-      // Since the sections are sorted by start address we only need to check
-      // whether the other sections starts before the end of Sec. If this is
-      // not the case we can break out of this loop since all following sections
-      // will also start after the end of Sec.
-      if (Start + Sec->Size <= GetStart(Other))
-        break;
-      errorOrWarn("section " + Sec->Name + " " + Kind +
+    OutputSection *Sec = Sections[I].Sec;
+    uint64_t Start = Sections[I].Offset;
+
+    for (size_t J = I + 1; J < Sections.size(); ++J) {
+      OutputSection *Other = Sections[J].Sec;
+      uint64_t OtherStart = Sections[J].Offset;
+      if (Start + Sec->Size <= OtherStart)
+        continue;
+
+      errorOrWarn("section " + Sec->Name + " " + Name +
                   " range overlaps with " + Other->Name + "\n>>> " + Sec->Name +
                   " range is " + rangeToString(Start, Sec->Size) + "\n>>> " +
                   Other->Name + " range is " +
-                  rangeToString(GetStart(Other), Other->Size));
+                  rangeToString(OtherStart, Other->Size));
     }
   }
 }
@@ -2017,19 +2018,18 @@ static void checkForSectionOverlap(Array
 // In this function we check that none of the output sections have overlapping
 // file offsets. For SHF_ALLOC sections we also check that the load address
 // ranges and the virtual address ranges don't overlap
-template <class ELFT> void Writer<ELFT>::checkNoOverlappingSections() {
+template <class ELFT> void Writer<ELFT>::checkSectionOverlap() {
   // First check for overlapping file offsets. In this case we need to skip
-  // Any section marked as SHT_NOBITS. These sections don't actually occupy
+  // any section marked as SHT_NOBITS. These sections don't actually occupy
   // space in the file so Sec->Offset + Sec->Size can overlap with others.
   // If --oformat binary is specified only add SHF_ALLOC sections are added to
   // the output file so we skip any non-allocated sections in that case.
-  checkForSectionOverlap(OutputSections, "file",
-                         [](const OutputSection *Sec) { return Sec->Offset; },
-                         [](const OutputSection *Sec) {
-                           return Sec->Type == SHT_NOBITS ||
-                                  (Config->OFormatBinary &&
-                                   (Sec->Flags & SHF_ALLOC) == 0);
-                         });
+  std::vector<SectionOffset> FileOffs;
+  for (OutputSection *Sec : OutputSections)
+    if (0 < Sec->Size && Sec->Type != SHT_NOBITS &&
+        (!Config->OFormatBinary || (Sec->Flags & SHF_ALLOC)))
+      FileOffs.push_back({Sec, Sec->Offset});
+  checkOverlap("file", FileOffs);
 
   // When linking with -r there is no need to check for overlapping virtual/load
   // addresses since those addresses will only be assigned when the final
@@ -2042,19 +2042,20 @@ template <class ELFT> void Writer<ELFT>:
   // Furthermore, we also need to skip SHF_TLS sections since these will be
   // mapped to other addresses at runtime and can therefore have overlapping
   // ranges in the file.
-  auto SkipNonAllocSections = [](const OutputSection *Sec) {
-    return (Sec->Flags & SHF_ALLOC) == 0 || (Sec->Flags & SHF_TLS);
-  };
-  checkForSectionOverlap(OutputSections, "virtual address",
-                         [](const OutputSection *Sec) { return Sec->Addr; },
-                         SkipNonAllocSections);
+  std::vector<SectionOffset> VMAs;
+  for (OutputSection *Sec : OutputSections)
+    if (0 < Sec->Size && (Sec->Flags & SHF_ALLOC) && !(Sec->Flags & SHF_TLS))
+      VMAs.push_back({Sec, Sec->Addr});
+  checkOverlap("virtual address", VMAs);
 
   // Finally, check that the load addresses don't overlap. This will usually be
   // the same as the virtual addresses but can be different when using a linker
   // script with AT().
-  checkForSectionOverlap(OutputSections, "load address",
-                         [](const OutputSection *Sec) { return Sec->getLMA(); },
-                         SkipNonAllocSections);
+  std::vector<SectionOffset> LMAs;
+  for (OutputSection *Sec : OutputSections)
+    if (0 < Sec->Size && (Sec->Flags & SHF_ALLOC) && !(Sec->Flags & SHF_TLS))
+      LMAs.push_back({Sec, Sec->getLMA()});
+  checkOverlap("load address", LMAs);
 }
 
 // The entry point address is chosen in the following ways.




More information about the llvm-commits mailing list