[ELF] Make createThunks a class [NFC]
authorPeter Smith <peter.smith@linaro.org>
Wed, 5 Apr 2017 10:30:09 +0000 (10:30 +0000)
committerPeter Smith <peter.smith@linaro.org>
Wed, 5 Apr 2017 10:30:09 +0000 (10:30 +0000)
For range extension thunks we will need to repeatedly call createThunks()
until no more thunks are created. We will need to retain the state of
Thunks that we have created so far to avoid recreating them on later
passes. This change does not change the functionality of createThunks().

Differential Revision: https://reviews.llvm.org/D31654

llvm-svn: 299530

lld/ELF/Relocations.cpp
lld/ELF/Relocations.h
lld/ELF/Writer.cpp

index 2b85cc61b57ae72ac3f35ac37b70cc871beb91ee..494aa7771dae79190b684f26889b6898ac322c7f 100644 (file)
@@ -932,8 +932,9 @@ template <class ELFT> void elf::scanRelocations(InputSectionBase &S) {
 // in the Sections vector, and recalculate the InputSection output section
 // offsets.
 // This may invalidate any output section offsets stored outside of InputSection
-static void mergeThunks(OutputSection *OS,
-                        std::vector<ThunkSection *> &Thunks) {
+template <class ELFT>
+void ThunkCreator<ELFT>::mergeThunks(OutputSection *OS,
+                                     std::vector<ThunkSection *> &Thunks) {
   // Order Thunks in ascending OutSecOff
   auto ThunkCmp = [](const ThunkSection *A, const ThunkSection *B) {
     return A->OutSecOff < B->OutSecOff;
@@ -961,6 +962,44 @@ static void mergeThunks(OutputSection *OS,
   OS->assignOffsets();
 }
 
+template <class ELFT>
+ThunkSection *ThunkCreator<ELFT>::getOSThunkSec(ThunkSection *&TS,
+                                                OutputSection *OS) {
+  if (TS == nullptr) {
+    uint32_t Off = 0;
+    for (auto *IS : OS->Sections) {
+      Off = IS->OutSecOff + IS->getSize();
+      if ((IS->Flags & SHF_EXECINSTR) == 0)
+        break;
+    }
+    TS = make<ThunkSection>(OS, Off);
+    ThunkSections[OS].push_back(TS);
+  }
+  return TS;
+}
+
+template <class ELFT>
+ThunkSection *ThunkCreator<ELFT>::getISThunkSec(InputSection *IS,
+                                                OutputSection *OS) {
+  ThunkSection *TS = ThunkedSections.lookup(IS);
+  if (TS)
+    return TS;
+  auto *TOS = cast<OutputSection>(IS->OutSec);
+  TS = make<ThunkSection>(TOS, IS->OutSecOff);
+  ThunkSections[TOS].push_back(TS);
+  ThunkedSections[IS] = TS;
+  return TS;
+}
+
+template <class ELFT>
+std::pair<Thunk *, bool> ThunkCreator<ELFT>::getThunk(SymbolBody &Body,
+                                                      uint32_t Type) {
+  auto res = ThunkedSymbols.insert({&Body, nullptr});
+  if (res.second)
+    res.first->second = addThunk<ELFT>(Type, Body);
+  return std::make_pair(res.first->second, res.second);
+}
+
 // Process all relocations from the InputSections that have been assigned
 // to OutputSections and redirect through Thunks if needed.
 //
@@ -972,48 +1011,8 @@ static void mergeThunks(OutputSection *OS,
 // FIXME: All Thunks are assumed to be in range of the relocation. Range
 // extension Thunks are not yet supported.
 template <class ELFT>
-bool elf::createThunks(ArrayRef<OutputSection *> OutputSections) {
-  // Track Symbols that already have a Thunk
-  DenseMap<SymbolBody *, Thunk *> ThunkedSymbols;
-  // Track InputSections that have a ThunkSection placed in front
-  DenseMap<InputSection *, ThunkSection *> ThunkedSections;
-  // Track the ThunksSections that need to be inserted into an OutputSection
-  std::map<OutputSection *, std::vector<ThunkSection *>> ThunkSections;
-
-  // Find or create a Thunk for Body for relocation Type
-  auto GetThunk = [&](SymbolBody &Body, uint32_t Type) {
-    auto res = ThunkedSymbols.insert({&Body, nullptr});
-    if (res.second == true)
-      res.first->second = addThunk<ELFT>(Type, Body);
-    return std::make_pair(res.first->second, res.second);
-  };
-
-  // Find or create a ThunkSection to be placed immediately before IS
-  auto GetISThunkSec = [&](InputSection *IS, OutputSection *OS) {
-    ThunkSection *TS = ThunkedSections.lookup(IS);
-    if (TS)
-      return TS;
-    auto *TOS = cast<OutputSection>(IS->OutSec);
-    TS = make<ThunkSection>(TOS, IS->OutSecOff);
-    ThunkSections[TOS].push_back(TS);
-    ThunkedSections[IS] = TS;
-    return TS;
-  };
-  // Find or create a ThunkSection to be placed as last executable section in
-  // OS.
-  auto GetOSThunkSec = [&](ThunkSection *&TS, OutputSection *OS) {
-    if (TS == nullptr) {
-      uint32_t Off = 0;
-      for (auto *IS : OS->Sections) {
-        Off = IS->OutSecOff + IS->getSize();
-        if ((IS->Flags & SHF_EXECINSTR) == 0)
-          break;
-      }
-      TS = make<ThunkSection>(OS, Off);
-      ThunkSections[OS].push_back(TS);
-    }
-    return TS;
-  };
+bool ThunkCreator<ELFT>::createThunks(
+    ArrayRef<OutputSection *> OutputSections) {
   // Create all the Thunks and insert them into synthetic ThunkSections. The
   // ThunkSections are later inserted back into the OutputSection.
 
@@ -1025,23 +1024,23 @@ bool elf::createThunks(ArrayRef<OutputSection *> OutputSections) {
     for (InputSection *IS : OS->Sections) {
       for (Relocation &Rel : IS->Relocations) {
         SymbolBody &Body = *Rel.Sym;
-        if (Target->needsThunk(Rel.Expr, Rel.Type, IS->File, Body)) {
-          Thunk *T;
-          bool IsNew;
-          std::tie(T, IsNew) = GetThunk(Body, Rel.Type);
-          if (IsNew) {
-            // Find or create a ThunkSection for the new Thunk
-            ThunkSection *TS;
-            if (auto *TIS = T->getTargetInputSection())
-              TS = GetISThunkSec(TIS, OS);
-            else
-              TS = GetOSThunkSec(OSTS, OS);
-            TS->addThunk(T);
-          }
-          // Redirect relocation to Thunk, we never go via the PLT to a Thunk
-          Rel.Sym = T->ThunkSym;
-          Rel.Expr = fromPlt(Rel.Expr);
+        if (!Target->needsThunk(Rel.Expr, Rel.Type, IS->File, Body))
+          continue;
+        Thunk *T;
+        bool IsNew;
+        std::tie(T, IsNew) = getThunk(Body, Rel.Type);
+        if (IsNew) {
+          // Find or create a ThunkSection for the new Thunk
+          ThunkSection *TS;
+          if (auto *TIS = T->getTargetInputSection())
+            TS = getISThunkSec(TIS, OS);
+          else
+            TS = getOSThunkSec(OSTS, OS);
+          TS->addThunk(T);
         }
+        // Redirect relocation to Thunk, we never go via the PLT to a Thunk
+        Rel.Sym = T->ThunkSym;
+        Rel.Expr = fromPlt(Rel.Expr);
       }
     }
   }
@@ -1057,7 +1056,7 @@ template void elf::scanRelocations<ELF32BE>(InputSectionBase &);
 template void elf::scanRelocations<ELF64LE>(InputSectionBase &);
 template void elf::scanRelocations<ELF64BE>(InputSectionBase &);
 
-template bool elf::createThunks<ELF32LE>(ArrayRef<OutputSection *>);
-template bool elf::createThunks<ELF32BE>(ArrayRef<OutputSection *>);
-template bool elf::createThunks<ELF64LE>(ArrayRef<OutputSection *>);
-template bool elf::createThunks<ELF64BE>(ArrayRef<OutputSection *>);
+template class elf::ThunkCreator<ELF32LE>;
+template class elf::ThunkCreator<ELF32BE>;
+template class elf::ThunkCreator<ELF64LE>;
+template class elf::ThunkCreator<ELF64BE>;
index b798dc3b29d0d8c7934c31ea350d7ceb1b500000..f8f0f11e14a906dc90a8decfe5f25249fbb76854 100644 (file)
@@ -11,6 +11,9 @@
 #define LLD_ELF_RELOCATIONS_H
 
 #include "lld/Core/LLVM.h"
+#include "llvm/ADT/DenseMap.h"
+#include <map>
+#include <vector>
 
 namespace lld {
 namespace elf {
@@ -113,8 +116,29 @@ struct Relocation {
 
 template <class ELFT> void scanRelocations(InputSectionBase &);
 
-template <class ELFT>
-bool createThunks(ArrayRef<OutputSection *> OutputSections);
+class ThunkSection;
+class Thunk;
+
+template <class ELFT> class ThunkCreator {
+public:
+  // Return true if Thunks have been added to OutputSections
+  bool createThunks(ArrayRef<OutputSection *> OutputSections);
+
+private:
+  void mergeThunks(OutputSection *OS, std::vector<ThunkSection *> &Thunks);
+  ThunkSection *getOSThunkSec(ThunkSection *&TS, OutputSection *OS);
+  ThunkSection *getISThunkSec(InputSection *IS, OutputSection *OS);
+  std::pair<Thunk *, bool> getThunk(SymbolBody &Body, uint32_t Type);
+
+  // Track Symbols that already have a Thunk
+  llvm::DenseMap<SymbolBody *, Thunk *> ThunkedSymbols;
+
+  // Track InputSections that have a ThunkSection placed in front
+  llvm::DenseMap<InputSection *, ThunkSection *> ThunkedSections;
+
+  // Track the ThunksSections that need to be inserted into an OutputSection
+  std::map<OutputSection *, std::vector<ThunkSection *>> ThunkSections;
+};
 
 // Return a int64_t to make sure we get the sign extension out of the way as
 // early as possible.
index deacc736d25b1bdcbffc76767663ff8b17f7a48e..53b2353539faa2f39b1ab406ef5c5ea2d46e657e 100644 (file)
@@ -1180,7 +1180,8 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
     // we need to assign addresses so that we can tell if jump instructions
     // are out of range. This will need to turn into a loop that converges
     // when no more Thunks are added
-    if (createThunks<ELFT>(OutputSections))
+    ThunkCreator<ELFT> TC;
+    if (TC.createThunks(OutputSections))
       applySynthetic({In<ELFT>::MipsGot},
                      [](SyntheticSection *SS) { SS->updateAllocSize(); });
   }