Finalize content of synthetic sections prior to Thunk Creation
    
This change moves the calls to finalizeContent() for each synthetic section
before createThunks(). This will allow us to assign addresses prior to
calling createThunks(). As addition of thunks may add to the static
symbol table and may affect the size of the mips got section we introduce a
couple of additional member functions to update these values.
    
Differential revision: https://reviews.llvm.org/D29983

llvm-svn: 297277
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index 8ef1d4d..c8039e6 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -895,7 +895,7 @@
 // FIXME: All Thunks are assumed to be in range of the relocation. Range
 // extension Thunks are not yet supported.
 template <class ELFT>
-void createThunks(ArrayRef<OutputSection *> OutputSections) {
+bool createThunks(ArrayRef<OutputSection *> OutputSections) {
   // Track Symbols that already have a Thunk
   DenseMap<SymbolBody *, Thunk<ELFT> *> ThunkedSymbols;
   // Track InputSections that have a ThunkSection placed in front
@@ -977,6 +977,7 @@
   // Merge all created synthetic ThunkSections back into OutputSection
   for (auto &KV : ThunkSections)
     mergeThunks<ELFT>(KV.first, KV.second);
+  return !ThunkSections.empty();
 }
 
 template void scanRelocations<ELF32LE>(InputSectionBase &);
@@ -984,9 +985,9 @@
 template void scanRelocations<ELF64LE>(InputSectionBase &);
 template void scanRelocations<ELF64BE>(InputSectionBase &);
 
-template void createThunks<ELF32LE>(ArrayRef<OutputSection *>);
-template void createThunks<ELF32BE>(ArrayRef<OutputSection *>);
-template void createThunks<ELF64LE>(ArrayRef<OutputSection *>);
-template void createThunks<ELF64BE>(ArrayRef<OutputSection *>);
+template bool createThunks<ELF32LE>(ArrayRef<OutputSection *>);
+template bool createThunks<ELF32BE>(ArrayRef<OutputSection *>);
+template bool createThunks<ELF64LE>(ArrayRef<OutputSection *>);
+template bool createThunks<ELF64BE>(ArrayRef<OutputSection *>);
 }
 }
diff --git a/lld/ELF/Relocations.h b/lld/ELF/Relocations.h
index e45d5fa..43eea12 100644
--- a/lld/ELF/Relocations.h
+++ b/lld/ELF/Relocations.h
@@ -112,7 +112,7 @@
 template <class ELFT> void scanRelocations(InputSectionBase &);
 
 template <class ELFT>
-void createThunks(ArrayRef<OutputSection *> OutputSections);
+bool createThunks(ArrayRef<OutputSection *> OutputSections);
 
 // Return a int64_t to make sure we get the sign extension out of the way as
 // early as possible.
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 7fb47eb..97d2d3a 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -844,6 +844,10 @@
 }
 
 template <class ELFT> void MipsGotSection<ELFT>::finalizeContents() {
+  updateAllocSize();
+}
+
+template <class ELFT> void MipsGotSection<ELFT>::updateAllocSize() {
   PageEntriesNum = 0;
   for (std::pair<const OutputSection *, size_t> &P : PageIndexMap) {
     // For each output section referenced by GOT page relocations calculate
@@ -1330,8 +1334,12 @@
       S.Symbol->DynsymIndex = ++I;
     return;
   }
+}
 
-  // If it is a .symtab, move all local symbols before global symbols.
+template <class ELFT> void SymbolTableSection<ELFT>::postThunkContents() {
+  if (this->Type == SHT_DYNSYM)
+    return;
+  // move all local symbols before global symbols.
   auto It = std::stable_partition(
       Symbols.begin(), Symbols.end(), [](const SymbolTableEntry &S) {
         return S.Symbol->isLocal() ||
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index 0b0dcd6..e7b47ac 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -43,6 +43,11 @@
   virtual void writeTo(uint8_t *Buf) = 0;
   virtual size_t getSize() const = 0;
   virtual void finalizeContents() {}
+  // If the section has the SHF_ALLOC flag and the size may be changed if
+  // thunks are added, update the section size.
+  virtual void updateAllocSize() {}
+  // If any additional finalization of contents are needed post thunk creation.
+  virtual void postThunkContents() {}
   virtual bool empty() const { return false; }
   uint64_t getVA() const;
 
@@ -168,6 +173,7 @@
   MipsGotSection();
   void writeTo(uint8_t *Buf) override;
   size_t getSize() const override { return Size; }
+  void updateAllocSize() override;
   void finalizeContents() override;
   bool empty() const override;
   void addEntry(SymbolBody &Sym, int64_t Addend, RelExpr Expr);
@@ -366,8 +372,6 @@
   };
 
   // finalizeContents() fills this vector with the section contents.
-  // finalizeContents()cannot directly create final section contents because
-  // when the function is called, symbol or section addresses are not fixed yet.
   std::vector<Entry> Entries;
 
 public:
@@ -416,6 +420,7 @@
   SymbolTableSection(StringTableSection<ELFT> &StrTabSec);
 
   void finalizeContents() override;
+  void postThunkContents() override;
   void writeTo(uint8_t *Buf) override;
   size_t getSize() const override { return getNumSymbols() * sizeof(Elf_Sym); }
   void addSymbol(SymbolBody *Body);
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 1b9039d..b29805d 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -1022,10 +1022,11 @@
 }
 
 template <class ELFT>
-static void finalizeSynthetic(const std::vector<SyntheticSection *> &Sections) {
+static void applySynthetic(const std::vector<SyntheticSection *> &Sections,
+                           std::function<void(SyntheticSection *)> Fn) {
   for (SyntheticSection *SS : Sections)
     if (SS && SS->OutSec && !SS->empty()) {
-      SS->finalizeContents();
+      Fn(SS);
       SS->OutSec->template assignOffsets<ELFT>();
     }
 }
@@ -1082,9 +1083,10 @@
   addRelIpltSymbols();
 
   // This responsible for splitting up .eh_frame section into
-  // pieces. The relocation scan uses those peaces, so this has to be
+  // pieces. The relocation scan uses those pieces, so this has to be
   // earlier.
-  finalizeSynthetic<ELFT>({In<ELFT>::EhFrame});
+  applySynthetic<ELFT>({In<ELFT>::EhFrame},
+                       [](SyntheticSection *SS) { SS->finalizeContents(); });
 
   // Scan relocations. This must be done after every symbol is declared so that
   // we can correctly decide if a dynamic relocation is needed.
@@ -1145,21 +1147,9 @@
     fixHeaders();
   }
 
-  // Some architectures use small displacements for jump instructions.
-  // It is linker's responsibility to create thunks containing long
-  // jump instructions if jump targets are too far. Create thunks.
-  if (Target->NeedsThunks)
-    createThunks<ELFT>(OutputSections);
-
-  // Fill other section headers. The dynamic table is finalized
-  // at the end because some tags like RELSZ depend on result
-  // of finalizing other sections.
-  for (OutputSection *Sec : OutputSections)
-    Sec->finalize<ELFT>();
-
   // Dynamic section must be the last one in this list and dynamic
   // symbol table section (DynSymTab) must be the first one.
-  finalizeSynthetic<ELFT>(
+  applySynthetic<ELFT>(
       {In<ELFT>::DynSymTab,  In<ELFT>::Bss,      In<ELFT>::BssRelRo,
        In<ELFT>::GnuHashTab, In<ELFT>::HashTab,  In<ELFT>::SymTab,
        In<ELFT>::ShStrTab,   In<ELFT>::StrTab,   In<ELFT>::VerDef,
@@ -1168,7 +1158,32 @@
        In<ELFT>::RelaDyn,    In<ELFT>::RelaIplt, In<ELFT>::RelaPlt,
        In<ELFT>::Plt,        In<ELFT>::Iplt,     In<ELFT>::Plt,
        In<ELFT>::EhFrameHdr, In<ELFT>::VerSym,   In<ELFT>::VerNeed,
-       In<ELFT>::Dynamic});
+       In<ELFT>::Dynamic},
+      [](SyntheticSection *SS) { SS->finalizeContents(); });
+
+  // Some architectures use small displacements for jump instructions.
+  // It is linker's responsibility to create thunks containing long
+  // jump instructions if jump targets are too far. Create thunks.
+  if (Target->NeedsThunks) {
+    // FIXME: only ARM Interworking and Mips LA25 Thunks are implemented,
+    // these
+    // do not require address information. To support range extension Thunks
+    // 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))
+      applySynthetic<ELFT>({In<ELFT>::MipsGot},
+                           [](SyntheticSection *SS) { SS->updateAllocSize(); });
+  }
+  // Fill other section headers. The dynamic table is finalized
+  // at the end because some tags like RELSZ depend on result
+  // of finalizing other sections.
+  for (OutputSection *Sec : OutputSections)
+    Sec->finalize<ELFT>();
+
+  // createThunks may have added local symbols to the static symbol table
+  applySynthetic<ELFT>({In<ELFT>::SymTab, In<ELFT>::ShStrTab, In<ELFT>::StrTab},
+                       [](SyntheticSection *SS) { SS->postThunkContents(); });
 }
 
 template <class ELFT> void Writer<ELFT>::addPredefinedSections() {