[lld] r328841 - ELF: Allow thunks to change size. NFCI.

Peter Collingbourne via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 29 15:32:13 PDT 2018


Author: pcc
Date: Thu Mar 29 15:32:13 2018
New Revision: 328841

URL: http://llvm.org/viewvc/llvm-project?rev=328841&view=rev
Log:
ELF: Allow thunks to change size. NFCI.

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

Modified:
    lld/trunk/ELF/Relocations.cpp
    lld/trunk/ELF/SyntheticSections.cpp
    lld/trunk/ELF/SyntheticSections.h
    lld/trunk/ELF/Thunks.cpp
    lld/trunk/ELF/Thunks.h

Modified: lld/trunk/ELF/Relocations.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.cpp?rev=328841&r1=328840&r2=328841&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.cpp (original)
+++ lld/trunk/ELF/Relocations.cpp Thu Mar 29 15:32:13 2018
@@ -1263,7 +1263,7 @@ std::pair<Thunk *, bool> ThunkCreator::g
   // Check existing Thunks for Sym to see if they can be reused
   for (Thunk *ET : *ThunkVec)
     if (ET->isCompatibleWith(Type) &&
-        Target->inBranchRange(Type, Src, ET->ThunkSym->getVA()))
+        Target->inBranchRange(Type, Src, ET->getThunkTargetSym()->getVA()))
       return std::make_pair(ET, false);
   // No existing compatible Thunk in range, create a new one
   Thunk *T = addThunk(Type, Sym);
@@ -1358,7 +1358,6 @@ bool ThunkCreator::createThunks(ArrayRef
             bool IsNew;
             std::tie(T, IsNew) = getThunk(*Rel.Sym, Rel.Type, Src);
             if (IsNew) {
-              AddressesChanged = true;
               // Find or create a ThunkSection for the new Thunk
               ThunkSection *TS;
               if (auto *TIS = T->getTargetInputSection())
@@ -1366,13 +1365,18 @@ bool ThunkCreator::createThunks(ArrayRef
               else
                 TS = getISDThunkSec(OS, IS, ISD, Rel.Type, Src);
               TS->addThunk(T);
-              Thunks[T->ThunkSym] = T;
+              Thunks[T->getThunkTargetSym()] = T;
             }
             // Redirect relocation to Thunk, we never go via the PLT to a Thunk
-            Rel.Sym = T->ThunkSym;
+            Rel.Sym = T->getThunkTargetSym();
             Rel.Expr = fromPlt(Rel.Expr);
           }
+        for (auto &P : ISD->ThunkSections)
+          AddressesChanged |= P.first->assignOffsets();
       });
+  for (auto &P : ThunkedSections)
+    AddressesChanged |= P.second->assignOffsets();
+
   // Merge all created synthetic ThunkSections back into OutputSection
   mergeThunks(OutputSections);
   ++Pass;

Modified: lld/trunk/ELF/SyntheticSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.cpp?rev=328841&r1=328840&r2=328841&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.cpp (original)
+++ lld/trunk/ELF/SyntheticSections.cpp Thu Mar 29 15:32:13 2018
@@ -264,8 +264,8 @@ InputSection *elf::createInterpSection()
   return Sec;
 }
 
-Symbol *elf::addSyntheticLocal(StringRef Name, uint8_t Type, uint64_t Value,
-                               uint64_t Size, InputSectionBase &Section) {
+Defined *elf::addSyntheticLocal(StringRef Name, uint8_t Type, uint64_t Value,
+                                uint64_t Size, InputSectionBase &Section) {
   auto *S = make<Defined>(Section.File, Name, STB_LOCAL, STV_DEFAULT, Type,
                           Value, Size, &Section);
   if (InX::SymTab)
@@ -2621,11 +2621,8 @@ ThunkSection::ThunkSection(OutputSection
 }
 
 void ThunkSection::addThunk(Thunk *T) {
-  uint64_t Off = alignTo(Size, T->Alignment);
-  T->Offset = Off;
   Thunks.push_back(T);
   T->addSymbols(*this);
-  Size = Off + T->size();
 }
 
 void ThunkSection::writeTo(uint8_t *Buf) {
@@ -2640,6 +2637,20 @@ InputSection *ThunkSection::getTargetInp
   return T->getTargetInputSection();
 }
 
+bool ThunkSection::assignOffsets() {
+  uint64_t Off = 0;
+  for (Thunk *T : Thunks) {
+    Off = alignTo(Off, T->Alignment);
+    T->setOffset(Off);
+    uint32_t Size = T->size();
+    T->getThunkTargetSym()->Size = Size;
+    Off += Size;
+  }
+  bool Changed = Off != Size;
+  Size = Off;
+  return Changed;
+}
+
 InputSection *InX::ARMAttributes;
 BssSection *InX::Bss;
 BssSection *InX::BssRelRo;

Modified: lld/trunk/ELF/SyntheticSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.h?rev=328841&r1=328840&r2=328841&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.h (original)
+++ lld/trunk/ELF/SyntheticSections.h Thu Mar 29 15:32:13 2018
@@ -30,6 +30,7 @@
 
 namespace lld {
 namespace elf {
+class Defined;
 class SharedSymbol;
 
 class SyntheticSection : public InputSection {
@@ -823,6 +824,7 @@ public:
   size_t getSize() const override { return Size; }
   void writeTo(uint8_t *Buf) override;
   InputSection *getTargetInputSection() const;
+  bool assignOffsets();
 
 private:
   std::vector<Thunk *> Thunks;
@@ -834,8 +836,8 @@ MergeInputSection *createCommentSection(
 void decompressSections();
 void mergeSections();
 
-Symbol *addSyntheticLocal(StringRef Name, uint8_t Type, uint64_t Value,
-                          uint64_t Size, InputSectionBase &Section);
+Defined *addSyntheticLocal(StringRef Name, uint8_t Type, uint64_t Value,
+                           uint64_t Size, InputSectionBase &Section);
 
 // Linker generated sections which can be used as inputs.
 struct InX {

Modified: lld/trunk/ELF/Thunks.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Thunks.cpp?rev=328841&r1=328840&r2=328841&view=diff
==============================================================================
--- lld/trunk/ELF/Thunks.cpp (original)
+++ lld/trunk/ELF/Thunks.cpp Thu Mar 29 15:32:13 2018
@@ -141,6 +141,19 @@ public:
 
 } // end anonymous namespace
 
+Defined *Thunk::addSymbol(StringRef Name, uint8_t Type, uint64_t Value,
+                          InputSectionBase &Section) {
+  Defined *D = addSyntheticLocal(Name, Type, Value, /*Size=*/0, Section);
+  Syms.push_back(D);
+  return D;
+}
+
+void Thunk::setOffset(uint64_t NewOffset) {
+  for (Defined *D : Syms)
+    D->Value = D->Value - Offset + NewOffset;
+  Offset = NewOffset;
+}
+
 // AArch64 long range Thunks
 
 static uint64_t getAArch64ThunkDestVA(const Symbol &S) {
@@ -161,11 +174,10 @@ void AArch64ABSLongThunk::writeTo(uint8_
 }
 
 void AArch64ABSLongThunk::addSymbols(ThunkSection &IS) {
-  ThunkSym = addSyntheticLocal(
-      Saver.save("__AArch64AbsLongThunk_" + Destination.getName()), STT_FUNC,
-      Offset, size(), IS);
-  addSyntheticLocal("$x", STT_NOTYPE, Offset, 0, IS);
-  addSyntheticLocal("$d", STT_NOTYPE, Offset + 8, 0, IS);
+  addSymbol(Saver.save("__AArch64AbsLongThunk_" + Destination.getName()),
+            STT_FUNC, 0, IS);
+  addSymbol("$x", STT_NOTYPE, 0, IS);
+  addSymbol("$d", STT_NOTYPE, 8, IS);
 }
 
 // This Thunk has a maximum range of 4Gb, this is sufficient for all programs
@@ -180,19 +192,17 @@ void AArch64ADRPThunk::writeTo(uint8_t *
       0x00, 0x02, 0x1f, 0xd6, // br   x16
   };
   uint64_t S = getAArch64ThunkDestVA(Destination);
-  uint64_t P = ThunkSym->getVA();
+  uint64_t P = getThunkTargetSym()->getVA();
   memcpy(Buf, Data, sizeof(Data));
   Target->relocateOne(Buf, R_AARCH64_ADR_PREL_PG_HI21,
                       getAArch64Page(S) - getAArch64Page(P));
   Target->relocateOne(Buf + 4, R_AARCH64_ADD_ABS_LO12_NC, S);
 }
 
-void AArch64ADRPThunk::addSymbols(ThunkSection &IS)
-{
-  ThunkSym = addSyntheticLocal(
-      Saver.save("__AArch64ADRPThunk_" + Destination.getName()), STT_FUNC,
-      Offset, size(), IS);
-  addSyntheticLocal("$x", STT_NOTYPE, Offset, 0, IS);
+void AArch64ADRPThunk::addSymbols(ThunkSection &IS) {
+  addSymbol(Saver.save("__AArch64ADRPThunk_" + Destination.getName()), STT_FUNC,
+            0, IS);
+  addSymbol("$x", STT_NOTYPE, 0, IS);
 }
 
 // ARM Target Thunks
@@ -214,10 +224,9 @@ void ARMV7ABSLongThunk::writeTo(uint8_t
 }
 
 void ARMV7ABSLongThunk::addSymbols(ThunkSection &IS) {
-  ThunkSym = addSyntheticLocal(
-      Saver.save("__ARMv7ABSLongThunk_" + Destination.getName()), STT_FUNC,
-      Offset, size(), IS);
-  addSyntheticLocal("$a", STT_NOTYPE, Offset, 0, IS);
+  addSymbol(Saver.save("__ARMv7ABSLongThunk_" + Destination.getName()),
+            STT_FUNC, 0, IS);
+  addSymbol("$a", STT_NOTYPE, 0, IS);
 }
 
 bool ARMV7ABSLongThunk::isCompatibleWith(RelType Type) const {
@@ -238,10 +247,9 @@ void ThumbV7ABSLongThunk::writeTo(uint8_
 }
 
 void ThumbV7ABSLongThunk::addSymbols(ThunkSection &IS) {
-  ThunkSym = addSyntheticLocal(
-      Saver.save("__Thumbv7ABSLongThunk_" + Destination.getName()), STT_FUNC,
-      Offset | 0x1, size(), IS);
-  addSyntheticLocal("$t", STT_NOTYPE, Offset, 0, IS);
+  addSymbol(Saver.save("__Thumbv7ABSLongThunk_" + Destination.getName()),
+            STT_FUNC, 1, IS);
+  addSymbol("$t", STT_NOTYPE, 0, IS);
 }
 
 bool ThumbV7ABSLongThunk::isCompatibleWith(RelType Type) const {
@@ -257,7 +265,7 @@ void ARMV7PILongThunk::writeTo(uint8_t *
       0x1c, 0xff, 0x2f, 0xe1, //     bx r12
   };
   uint64_t S = getARMThunkDestVA(Destination);
-  uint64_t P = ThunkSym->getVA();
+  uint64_t P = getThunkTargetSym()->getVA();
   uint64_t Offset = S - P - 16;
   memcpy(Buf, Data, sizeof(Data));
   Target->relocateOne(Buf, R_ARM_MOVW_PREL_NC, Offset);
@@ -265,10 +273,9 @@ void ARMV7PILongThunk::writeTo(uint8_t *
 }
 
 void ARMV7PILongThunk::addSymbols(ThunkSection &IS) {
-  ThunkSym = addSyntheticLocal(
-      Saver.save("__ARMV7PILongThunk_" + Destination.getName()), STT_FUNC,
-      Offset, size(), IS);
-  addSyntheticLocal("$a", STT_NOTYPE, Offset, 0, IS);
+  addSymbol(Saver.save("__ARMV7PILongThunk_" + Destination.getName()), STT_FUNC,
+            0, IS);
+  addSymbol("$a", STT_NOTYPE, 0, IS);
 }
 
 bool ARMV7PILongThunk::isCompatibleWith(RelType Type) const {
@@ -284,7 +291,7 @@ void ThumbV7PILongThunk::writeTo(uint8_t
       0x60, 0x47,             //     bx   r12
   };
   uint64_t S = getARMThunkDestVA(Destination);
-  uint64_t P = ThunkSym->getVA() & ~0x1;
+  uint64_t P = getThunkTargetSym()->getVA() & ~0x1;
   uint64_t Offset = S - P - 12;
   memcpy(Buf, Data, sizeof(Data));
   Target->relocateOne(Buf, R_ARM_THM_MOVW_PREL_NC, Offset);
@@ -292,10 +299,9 @@ void ThumbV7PILongThunk::writeTo(uint8_t
 }
 
 void ThumbV7PILongThunk::addSymbols(ThunkSection &IS) {
-  ThunkSym = addSyntheticLocal(
-      Saver.save("__ThumbV7PILongThunk_" + Destination.getName()), STT_FUNC,
-      Offset | 0x1, size(), IS);
-  addSyntheticLocal("$t", STT_NOTYPE, Offset, 0, IS);
+  addSymbol(Saver.save("__ThumbV7PILongThunk_" + Destination.getName()),
+            STT_FUNC, 1, IS);
+  addSymbol("$t", STT_NOTYPE, 0, IS);
 }
 
 bool ThumbV7PILongThunk::isCompatibleWith(RelType Type) const {
@@ -315,9 +321,8 @@ void MipsThunk::writeTo(uint8_t *Buf) {
 }
 
 void MipsThunk::addSymbols(ThunkSection &IS) {
-  ThunkSym =
-      addSyntheticLocal(Saver.save("__LA25Thunk_" + Destination.getName()),
-                        STT_FUNC, Offset, size(), IS);
+  addSymbol(Saver.save("__LA25Thunk_" + Destination.getName()), STT_FUNC, 0,
+            IS);
 }
 
 InputSection *MipsThunk::getTargetInputSection() const {
@@ -339,10 +344,9 @@ void MicroMipsThunk::writeTo(uint8_t *Bu
 }
 
 void MicroMipsThunk::addSymbols(ThunkSection &IS) {
-  ThunkSym =
-      addSyntheticLocal(Saver.save("__microLA25Thunk_" + Destination.getName()),
-                        STT_FUNC, Offset, size(), IS);
-  ThunkSym->StOther |= STO_MIPS_MICROMIPS;
+  Defined *D = addSymbol(
+      Saver.save("__microLA25Thunk_" + Destination.getName()), STT_FUNC, 0, IS);
+  D->StOther |= STO_MIPS_MICROMIPS;
 }
 
 InputSection *MicroMipsThunk::getTargetInputSection() const {
@@ -354,7 +358,7 @@ InputSection *MicroMipsThunk::getTargetI
 // to call PIC function from the non-PIC one.
 void MicroMipsR6Thunk::writeTo(uint8_t *Buf) {
   uint64_t S = Destination.getVA() | 1;
-  uint64_t P = ThunkSym->getVA();
+  uint64_t P = getThunkTargetSym()->getVA();
   write16(Buf, 0x1320);       // lui   $25, %hi(func)
   write16(Buf + 4, 0x3339);   // addiu $25, $25, %lo(func)
   write16(Buf + 8, 0x9400);   // bc    func
@@ -364,10 +368,9 @@ void MicroMipsR6Thunk::writeTo(uint8_t *
 }
 
 void MicroMipsR6Thunk::addSymbols(ThunkSection &IS) {
-  ThunkSym =
-      addSyntheticLocal(Saver.save("__microLA25Thunk_" + Destination.getName()),
-                        STT_FUNC, Offset, size(), IS);
-  ThunkSym->StOther |= STO_MIPS_MICROMIPS;
+  Defined *D = addSymbol(
+      Saver.save("__microLA25Thunk_" + Destination.getName()), STT_FUNC, 0, IS);
+  D->StOther |= STO_MIPS_MICROMIPS;
 }
 
 InputSection *MicroMipsR6Thunk::getTargetInputSection() const {

Modified: lld/trunk/ELF/Thunks.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Thunks.h?rev=328841&r1=328840&r2=328841&view=diff
==============================================================================
--- lld/trunk/ELF/Thunks.h (original)
+++ lld/trunk/ELF/Thunks.h Thu Mar 29 15:32:13 2018
@@ -14,6 +14,7 @@
 
 namespace lld {
 namespace elf {
+class Defined;
 class Symbol;
 class ThunkSection;
 // Class to describe an instance of a Thunk.
@@ -33,10 +34,15 @@ public:
   virtual uint32_t size() = 0;
   virtual void writeTo(uint8_t *Buf) = 0;
 
-  // All Thunks must define at least one symbol ThunkSym so that we can
-  // redirect relocations to it.
+  // All Thunks must define at least one symbol, known as the thunk target
+  // symbol, so that we can redirect relocations to it. The thunk may define
+  // additional symbols, but these are never targets for relocations.
   virtual void addSymbols(ThunkSection &IS) = 0;
 
+  void setOffset(uint64_t Offset);
+  Defined *addSymbol(StringRef Name, uint8_t Type, uint64_t Value,
+                     InputSectionBase &Section);
+
   // Some Thunks must be placed immediately before their Target as they elide
   // a branch and fall through to the first Symbol in the Target.
   virtual InputSection *getTargetInputSection() const { return nullptr; }
@@ -45,10 +51,12 @@ public:
   // compatible with it.
   virtual bool isCompatibleWith(RelType Type) const { return true; }
 
+  Defined *getThunkTargetSym() const { return Syms[0]; }
+
   // The alignment requirement for this Thunk, defaults to the size of the
   // typical code section alignment.
   Symbol &Destination;
-  Symbol *ThunkSym;
+  llvm::SmallVector<Defined *, 3> Syms;
   uint64_t Offset = 0;
   uint32_t Alignment = 4;
 };




More information about the llvm-commits mailing list