[lld] r292359 - [ELF] Move createThunks() after scanRelocations()

Peter Smith via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 18 01:57:14 PST 2017


Author: psmith
Date: Wed Jan 18 03:57:14 2017
New Revision: 292359

URL: http://llvm.org/viewvc/llvm-project?rev=292359&view=rev
Log:
[ELF] Move createThunks() after scanRelocations()
    
A necessary first step towards range extension thunks is to delay
the creation of thunks until the layout of InputSections within
OutputSections has been done.
    
The change scans the relocations directly from InputSections rather
than looking in the ELF File the InputSection came from. This will
allow a future change to redirect the relocations to symbols defined
by Thunks rather than indirect when resolving relocations.
    
A side-effect of moving ThunkCreation is that the OutSecOff of
InputSections may change in an OutputSection that contains Thunks.
In well behaved programs thunks are not in OutputSections with
dynamic relocations.
    
Differential Revision: https://reviews.llvm.org/D28811


Modified:
    lld/trunk/ELF/Relocations.cpp
    lld/trunk/ELF/Relocations.h
    lld/trunk/ELF/Target.cpp
    lld/trunk/ELF/Target.h
    lld/trunk/ELF/Writer.cpp

Modified: lld/trunk/ELF/Relocations.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.cpp?rev=292359&r1=292358&r2=292359&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.cpp (original)
+++ lld/trunk/ELF/Relocations.cpp Wed Jan 18 03:57:14 2017
@@ -467,7 +467,7 @@ static RelExpr adjustExpr(const elf::Obj
     if (Expr == R_GOT_PC && !isAbsoluteValue<ELFT>(Body))
       Expr = Target->adjustRelaxExpr(Type, Data, Expr);
   }
-  Expr = Target->getThunkExpr(Expr, Type, File, Body);
+  Expr = Target->getThunkExpr(Expr, Type, &File, Body);
 
   if (IsWrite || isStaticLinkTimeConstant<ELFT>(Expr, Type, Body, S, RelOff))
     return Expr;
@@ -805,31 +805,38 @@ template <class ELFT> void scanRelocatio
     scanRelocs(S, S.rels());
 }
 
-template <class ELFT, class RelTy>
-static void createThunks(InputSectionBase<ELFT> &C, ArrayRef<RelTy> Rels) {
-  const elf::ObjectFile<ELFT> *File = C.getFile();
-  for (const RelTy &Rel : Rels) {
-    SymbolBody &Body = File->getRelocTargetSym(Rel);
-    uint32_t Type = Rel.getType(Config->Mips64EL);
-    RelExpr Expr = Target->getRelExpr(Type, Body);
-    if (!isPreemptible(Body, Type) && needsPlt(Expr))
-      Expr = fromPlt(Expr);
-    Expr = Target->getThunkExpr(Expr, Type, *File, Body);
-    // Some targets might require creation of thunks for relocations.
-    // Now we support only MIPS which requires LA25 thunk to call PIC
-    // code from non-PIC one, and ARM which requires interworking.
-    if (Expr == R_THUNK_ABS || Expr == R_THUNK_PC || Expr == R_THUNK_PLT_PC) {
-      auto *Sec = cast<InputSection<ELFT>>(&C);
-      addThunk<ELFT>(Type, Body, *Sec);
+template <class ELFT>
+void createThunks(ArrayRef<OutputSectionBase *> OutputSections) {
+  for (OutputSectionBase *Base : OutputSections) {
+    if (auto *OS = dyn_cast<OutputSection<ELFT>>(Base)) {
+      for (InputSection<ELFT> *IS : OS->Sections) {
+        for (const Relocation &Rel : IS->Relocations) {
+          if (Rel.Sym == nullptr) {
+            continue;
+          }
+          SymbolBody &Body = *Rel.Sym;
+          uint32_t Type = Rel.Type;
+          RelExpr Expr = Rel.Expr;
+          if (!isPreemptible(Body, Type) && needsPlt(Expr))
+            Expr = fromPlt(Expr);
+          Expr = Target->getThunkExpr(Expr, Type, IS->getFile(), Body);
+          // Some targets might require creation of thunks for relocations.
+          // Now we support only MIPS which requires LA25 thunk to call PIC
+          // code from non-PIC one, and ARM which requires interworking.
+          if (Expr == R_THUNK_ABS || Expr == R_THUNK_PC ||
+              Expr == R_THUNK_PLT_PC)
+            addThunk<ELFT>(Type, Body, *IS);
+        }
+      }
     }
   }
-}
-
-template <class ELFT> void createThunks(InputSectionBase<ELFT> &S) {
-  if (S.AreRelocsRela)
-    createThunks(S, S.relas());
-  else
-    createThunks(S, S.rels());
+  // Added thunks may affect the output section offset
+  for (OutputSectionBase *Base : OutputSections)
+    if (auto *OS = dyn_cast<OutputSection<ELFT>>(Base))
+      if (OS->Type == SHT_PROGBITS) {
+        OS->Size = 0;
+        OS->assignOffsets();
+      }
 }
 
 template void scanRelocations<ELF32LE>(InputSectionBase<ELF32LE> &);
@@ -837,9 +844,9 @@ template void scanRelocations<ELF32BE>(I
 template void scanRelocations<ELF64LE>(InputSectionBase<ELF64LE> &);
 template void scanRelocations<ELF64BE>(InputSectionBase<ELF64BE> &);
 
-template void createThunks<ELF32LE>(InputSectionBase<ELF32LE> &);
-template void createThunks<ELF32BE>(InputSectionBase<ELF32BE> &);
-template void createThunks<ELF64LE>(InputSectionBase<ELF64LE> &);
-template void createThunks<ELF64BE>(InputSectionBase<ELF64BE> &);
+template void createThunks<ELF32LE>(ArrayRef<OutputSectionBase *>);
+template void createThunks<ELF32BE>(ArrayRef<OutputSectionBase *>);
+template void createThunks<ELF64LE>(ArrayRef<OutputSectionBase *>);
+template void createThunks<ELF64BE>(ArrayRef<OutputSectionBase *>);
 }
 }

Modified: lld/trunk/ELF/Relocations.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.h?rev=292359&r1=292358&r2=292359&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.h (original)
+++ lld/trunk/ELF/Relocations.h Wed Jan 18 03:57:14 2017
@@ -18,6 +18,7 @@ class SymbolBody;
 class InputSectionData;
 template <class ELFT> class InputSection;
 template <class ELFT> class InputSectionBase;
+class OutputSectionBase;
 
 // List of target-independent relocation types. Relocations read
 // from files are converted to these types so that the main code
@@ -113,7 +114,8 @@ struct Relocation {
 
 template <class ELFT> void scanRelocations(InputSectionBase<ELFT> &);
 
-template <class ELFT> void createThunks(InputSectionBase<ELFT> &);
+template <class ELFT>
+void createThunks(ArrayRef<OutputSectionBase *> OutputSections);
 
 template <class ELFT>
 static inline typename ELFT::uint getAddend(const typename ELFT::Rel &Rel) {

Modified: lld/trunk/ELF/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.cpp?rev=292359&r1=292358&r2=292359&view=diff
==============================================================================
--- lld/trunk/ELF/Target.cpp (original)
+++ lld/trunk/ELF/Target.cpp Wed Jan 18 03:57:14 2017
@@ -223,7 +223,7 @@ public:
   void writePltHeader(uint8_t *Buf) const override;
   void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr,
                 int32_t Index, unsigned RelOff) const override;
-  RelExpr getThunkExpr(RelExpr Expr, uint32_t RelocType, const InputFile &File,
+  RelExpr getThunkExpr(RelExpr Expr, uint32_t RelocType, const InputFile *File,
                        const SymbolBody &S) const override;
   void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override;
 };
@@ -241,7 +241,7 @@ public:
   void writePltHeader(uint8_t *Buf) const override;
   void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr,
                 int32_t Index, unsigned RelOff) const override;
-  RelExpr getThunkExpr(RelExpr Expr, uint32_t RelocType, const InputFile &File,
+  RelExpr getThunkExpr(RelExpr Expr, uint32_t RelocType, const InputFile *File,
                        const SymbolBody &S) const override;
   void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override;
   bool usesOnlyLowPageBits(uint32_t Type) const override;
@@ -294,7 +294,7 @@ uint64_t TargetInfo::getImplicitAddend(c
 bool TargetInfo::usesOnlyLowPageBits(uint32_t Type) const { return false; }
 
 RelExpr TargetInfo::getThunkExpr(RelExpr Expr, uint32_t RelocType,
-                                 const InputFile &File,
+                                 const InputFile *File,
                                  const SymbolBody &S) const {
   return Expr;
 }
@@ -1749,13 +1749,13 @@ void ARMTargetInfo::writePlt(uint8_t *Bu
 }
 
 RelExpr ARMTargetInfo::getThunkExpr(RelExpr Expr, uint32_t RelocType,
-                                    const InputFile &File,
+                                    const InputFile *File,
                                     const SymbolBody &S) const {
   // If S is an undefined weak symbol in an executable we don't need a Thunk.
   // In a DSO calls to undefined symbols, including weak ones get PLT entries
   // which may need a thunk.
-  if (S.isUndefined() && !S.isLocal() && S.symbol()->isWeak()
-      && !Config->Shared)
+  if (S.isUndefined() && !S.isLocal() && S.symbol()->isWeak() &&
+      !Config->Shared)
     return Expr;
   // A state change from ARM to Thumb and vice versa must go through an
   // interworking thunk if the relocation type is not R_ARM_CALL or
@@ -2193,7 +2193,7 @@ void MipsTargetInfo<ELFT>::writePlt(uint
 
 template <class ELFT>
 RelExpr MipsTargetInfo<ELFT>::getThunkExpr(RelExpr Expr, uint32_t Type,
-                                           const InputFile &File,
+                                           const InputFile *File,
                                            const SymbolBody &S) const {
   // Any MIPS PIC code function is invoked with its address in register $t9.
   // So if we have a branch instruction from non-PIC code to the PIC one
@@ -2202,7 +2202,7 @@ RelExpr MipsTargetInfo<ELFT>::getThunkEx
   // See page 3-38 ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
   if (Type != R_MIPS_26)
     return Expr;
-  auto *F = dyn_cast<ELFFileBase<ELFT>>(&File);
+  auto *F = dyn_cast_or_null<ELFFileBase<ELFT>>(File);
   if (!F)
     return Expr;
   // If current file has PIC code, LA25 stub is not required.

Modified: lld/trunk/ELF/Target.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.h?rev=292359&r1=292358&r2=292359&view=diff
==============================================================================
--- lld/trunk/ELF/Target.h (original)
+++ lld/trunk/ELF/Target.h Wed Jan 18 03:57:14 2017
@@ -56,7 +56,7 @@ public:
   // R_THUNK_PC if thunk is required and expression is pc rel
   // R_THUNK_PLT_PC if thunk is required to PLT entry and expression is pc rel
   virtual RelExpr getThunkExpr(RelExpr Expr, uint32_t RelocType,
-                               const InputFile &File,
+                               const InputFile *File,
                                const SymbolBody &S) const;
   virtual RelExpr getRelExpr(uint32_t Type, const SymbolBody &S) const = 0;
   virtual void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const = 0;

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=292359&r1=292358&r2=292359&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Wed Jan 18 03:57:14 2017
@@ -158,12 +158,6 @@ template <class ELFT> void Writer<ELFT>:
   if (!Config->Relocatable)
     addReservedSymbols();
 
-  // 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)
-    forEachRelSec(createThunks<ELFT>);
-
   // Create output sections.
   Script<ELFT>::X->OutputSections = &OutputSections;
   if (ScriptConfig->HasSections) {
@@ -1088,6 +1082,12 @@ template <class ELFT> void Writer<ELFT>:
     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.




More information about the llvm-commits mailing list