[lld] r290951 - [ELF] Add support for thunks to undefined non-weak symbols

Peter Smith via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 4 01:45:46 PST 2017


Author: psmith
Date: Wed Jan  4 03:45:45 2017
New Revision: 290951

URL: http://llvm.org/viewvc/llvm-project?rev=290951&view=rev
Log:
[ELF] Add support for thunks to undefined non-weak symbols
    
In a shared library an undefined symbol is implicitly imported. If the
symbol is called as a function a PLT entry is generated for it. When the
caller is a Thumb b.w a thunk to the PLT entry is needed as all PLT
entries are in ARM state.
    
This change allows undefined symbols to have thunks in the same way that
shared symbols may have thunks.


Added:
    lld/trunk/test/ELF/arm-thumb-interwork-shared.s
Modified:
    lld/trunk/ELF/InputFiles.cpp
    lld/trunk/ELF/LTO.cpp
    lld/trunk/ELF/LTO.h
    lld/trunk/ELF/SymbolTable.cpp
    lld/trunk/ELF/Symbols.cpp
    lld/trunk/ELF/Symbols.h
    lld/trunk/ELF/Target.cpp
    lld/trunk/ELF/Thunks.cpp

Modified: lld/trunk/ELF/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.cpp?rev=290951&r1=290950&r2=290951&view=diff
==============================================================================
--- lld/trunk/ELF/InputFiles.cpp (original)
+++ lld/trunk/ELF/InputFiles.cpp Wed Jan  4 03:45:45 2017
@@ -461,7 +461,7 @@ SymbolBody *elf::ObjectFile<ELFT>::creat
     StringRefZ Name = this->StringTable.data() + Sym->st_name;
     if (Sym->st_shndx == SHN_UNDEF)
       return new (BAlloc)
-          Undefined(Name, /*IsLocal=*/true, StOther, Type, this);
+          Undefined<ELFT>(Name, /*IsLocal=*/true, StOther, Type, this);
 
     return new (BAlloc) DefinedRegular<ELFT>(Name, /*IsLocal=*/true, StOther,
                                              Type, Value, Size, Sec, this);

Modified: lld/trunk/ELF/LTO.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LTO.cpp?rev=290951&r1=290950&r2=290951&view=diff
==============================================================================
--- lld/trunk/ELF/LTO.cpp (original)
+++ lld/trunk/ELF/LTO.cpp Wed Jan  4 03:45:45 2017
@@ -96,12 +96,12 @@ BitcodeCompiler::BitcodeCompiler() : LTO
 
 BitcodeCompiler::~BitcodeCompiler() = default;
 
-static void undefine(Symbol *S) {
-  replaceBody<Undefined>(S, S->body()->getName(), /*IsLocal=*/false,
-                         STV_DEFAULT, S->body()->Type, nullptr);
+template <class ELFT> static void undefine(Symbol *S) {
+  replaceBody<Undefined<ELFT>>(S, S->body()->getName(), /*IsLocal=*/false,
+                               STV_DEFAULT, S->body()->Type, nullptr);
 }
 
-void BitcodeCompiler::add(BitcodeFile &F) {
+template <class ELFT> void BitcodeCompiler::add(BitcodeFile &F) {
   lto::InputFile &Obj = *F.Obj;
   unsigned SymNum = 0;
   std::vector<Symbol *> Syms = F.getSymbols();
@@ -126,7 +126,7 @@ void BitcodeCompiler::add(BitcodeFile &F
     R.VisibleToRegularObj =
         Sym->IsUsedInRegularObj || (R.Prevailing && Sym->includeInDynsym());
     if (R.Prevailing)
-      undefine(Sym);
+      undefine<ELFT>(Sym);
   }
   checkError(LTOObj->add(std::move(F.Obj), Resols));
 }
@@ -157,3 +157,8 @@ std::vector<InputFile *> BitcodeCompiler
   }
   return Ret;
 }
+
+template void BitcodeCompiler::template add<ELF32LE>(BitcodeFile &);
+template void BitcodeCompiler::template add<ELF32BE>(BitcodeFile &);
+template void BitcodeCompiler::template add<ELF64LE>(BitcodeFile &);
+template void BitcodeCompiler::template add<ELF64BE>(BitcodeFile &);

Modified: lld/trunk/ELF/LTO.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LTO.h?rev=290951&r1=290950&r2=290951&view=diff
==============================================================================
--- lld/trunk/ELF/LTO.h (original)
+++ lld/trunk/ELF/LTO.h Wed Jan  4 03:45:45 2017
@@ -43,7 +43,7 @@ public:
   BitcodeCompiler();
   ~BitcodeCompiler();
 
-  void add(BitcodeFile &F);
+  template <class ELFT> void add(BitcodeFile &F);
   std::vector<InputFile *> compile();
 
 private:

Modified: lld/trunk/ELF/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.cpp?rev=290951&r1=290950&r2=290951&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.cpp (original)
+++ lld/trunk/ELF/SymbolTable.cpp Wed Jan  4 03:45:45 2017
@@ -115,7 +115,7 @@ template <class ELFT> void SymbolTable<E
   // Compile bitcode files and replace bitcode symbols.
   LTO.reset(new BitcodeCompiler);
   for (BitcodeFile *F : BitcodeFiles)
-    LTO->add(*F);
+    LTO->add<ELFT>(*F);
 
   for (InputFile *File : LTO->compile()) {
     ObjectFile<ELFT> *Obj = cast<ObjectFile<ELFT>>(File);
@@ -256,7 +256,7 @@ Symbol *SymbolTable<ELFT>::addUndefined(
       insert(Name, Type, getVisibility(StOther), CanOmitFromDynSym, File);
   if (WasInserted) {
     S->Binding = Binding;
-    replaceBody<Undefined>(S, Name, IsLocal, StOther, Type, File);
+    replaceBody<Undefined<ELFT>>(S, Name, IsLocal, StOther, Type, File);
     return S;
   }
   if (Binding != STB_WEAK) {
@@ -432,7 +432,7 @@ void SymbolTable<ELFT>::addShared(Shared
     if (S->VersionId == VER_NDX_LOCAL)
       S->VersionId = VER_NDX_GLOBAL;
   }
-  if (WasInserted || isa<Undefined>(S->body())) {
+  if (WasInserted || isa<Undefined<ELFT>>(S->body())) {
     replaceBody<SharedSymbol<ELFT>>(S, F, Name, Sym, Verdef);
     if (!S->isWeak())
       F->IsUsed = true;

Modified: lld/trunk/ELF/Symbols.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.cpp?rev=290951&r1=290950&r2=290951&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.cpp (original)
+++ lld/trunk/ELF/Symbols.cpp Wed Jan  4 03:45:45 2017
@@ -173,6 +173,8 @@ template <class ELFT> typename ELFT::uin
     return DR->ThunkData->getVA();
   if (const auto *S = dyn_cast<SharedSymbol<ELFT>>(this))
     return S->ThunkData->getVA();
+  if (const auto *S = dyn_cast<Undefined<ELFT>>(this))
+    return S->ThunkData->getVA();
   fatal("getThunkVA() not supported for Symbol class\n");
 }
 
@@ -232,8 +234,9 @@ template <class ELFT> bool DefinedRegula
          (Section->getFile()->getObj().getHeader()->e_flags & EF_MIPS_PIC);
 }
 
-Undefined::Undefined(StringRefZ Name, bool IsLocal, uint8_t StOther,
-                     uint8_t Type, InputFile *File)
+template <typename ELFT>
+Undefined<ELFT>::Undefined(StringRefZ Name, bool IsLocal, uint8_t StOther,
+                           uint8_t Type, InputFile *File)
     : SymbolBody(SymbolBody::UndefinedKind, Name, IsLocal, StOther, Type) {
   this->File = File;
 }
@@ -354,6 +357,11 @@ template uint32_t SymbolBody::template g
 template uint64_t SymbolBody::template getSize<ELF64LE>() const;
 template uint64_t SymbolBody::template getSize<ELF64BE>() const;
 
+template class elf::Undefined<ELF32LE>;
+template class elf::Undefined<ELF32BE>;
+template class elf::Undefined<ELF64LE>;
+template class elf::Undefined<ELF64BE>;
+
 template class elf::DefinedRegular<ELF32LE>;
 template class elf::DefinedRegular<ELF32BE>;
 template class elf::DefinedRegular<ELF64LE>;

Modified: lld/trunk/ELF/Symbols.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.h?rev=290951&r1=290950&r2=290951&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.h (original)
+++ lld/trunk/ELF/Symbols.h Wed Jan  4 03:45:45 2017
@@ -236,7 +236,7 @@ public:
   const OutputSectionBase *Section;
 };
 
-class Undefined : public SymbolBody {
+template <class ELFT> class Undefined : public SymbolBody {
 public:
   Undefined(StringRefZ Name, bool IsLocal, uint8_t StOther, uint8_t Type,
             InputFile *F);
@@ -245,6 +245,12 @@ public:
     return S->kind() == UndefinedKind;
   }
 
+  // If non-null the symbol has a Thunk that may be used as an alternative
+  // destination for callers of this Symbol. When linking a DSO undefined
+  // symbols are implicitly imported, the symbol lookup will be performed by
+  // the dynamic loader. A call to an undefined symbol will be given a PLT
+  // entry and on ARM this may need a Thunk if the caller is in Thumb state.
+  Thunk<ELFT> *ThunkData = nullptr;
   InputFile *file() { return this->File; }
 };
 
@@ -416,7 +422,8 @@ struct Symbol {
   // ELFT, and we verify this with the static_asserts in replaceBody.
   llvm::AlignedCharArrayUnion<
       DefinedCommon, DefinedRegular<llvm::object::ELF64LE>, DefinedSynthetic,
-      Undefined, SharedSymbol<llvm::object::ELF64LE>, LazyArchive, LazyObject>
+      Undefined<llvm::object::ELF64LE>, SharedSymbol<llvm::object::ELF64LE>,
+      LazyArchive, LazyObject>
       Body;
 
   SymbolBody *body() { return reinterpret_cast<SymbolBody *>(Body.buffer); }

Modified: lld/trunk/ELF/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.cpp?rev=290951&r1=290950&r2=290951&view=diff
==============================================================================
--- lld/trunk/ELF/Target.cpp (original)
+++ lld/trunk/ELF/Target.cpp Wed Jan  4 03:45:45 2017
@@ -1730,8 +1730,11 @@ void ARMTargetInfo::writePlt(uint8_t *Bu
 RelExpr ARMTargetInfo::getThunkExpr(RelExpr Expr, uint32_t RelocType,
                                     const InputFile &File,
                                     const SymbolBody &S) const {
-  // If S is an undefined weak symbol we don't need a Thunk
-  if (S.isUndefined())
+  // 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)
     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

Modified: lld/trunk/ELF/Thunks.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Thunks.cpp?rev=290951&r1=290950&r2=290951&view=diff
==============================================================================
--- lld/trunk/ELF/Thunks.cpp (original)
+++ lld/trunk/ELF/Thunks.cpp Wed Jan  4 03:45:45 2017
@@ -226,6 +226,8 @@ static void addThunkARM(uint32_t Reloc,
     Sym->ThunkData = T;
   else if (auto *Sym = dyn_cast<SharedSymbol<ELFT>>(&S))
     Sym->ThunkData = T;
+  else if (auto *Sym = dyn_cast<Undefined<ELFT>>(&S))
+    Sym->ThunkData = T;
   else
     fatal("symbol not DefinedRegular or Shared");
 }

Added: lld/trunk/test/ELF/arm-thumb-interwork-shared.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/arm-thumb-interwork-shared.s?rev=290951&view=auto
==============================================================================
--- lld/trunk/test/ELF/arm-thumb-interwork-shared.s (added)
+++ lld/trunk/test/ELF/arm-thumb-interwork-shared.s Wed Jan  4 03:45:45 2017
@@ -0,0 +1,44 @@
+// RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t
+// RUN: ld.lld %t --shared -o %t.so
+// RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi %t.so | FileCheck %s
+// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t.so | FileCheck %s -check-prefix=PLT
+// REQUIRES: arm
+ .syntax unified
+ .global sym1
+ .global elsewhere
+ .weak weakref
+sym1:
+ b.w elsewhere
+ b.w weakref
+
+// Check that we generate a thunk for an undefined symbol called via a plt
+// entry.
+
+// CHECK: Disassembly of section .text:
+// CHECK-NEXT: sym1:
+// CHECK:          1000:       00 f0 02 b8     b.w     #4
+// CHECK-NEXT:     1004:       00 f0 06 b8     b.w     #12
+// CHECK-NEXT:     1008:       40 f2 20 0c     movw    r12, #32
+// CHECK-NEXT:     100c:       c0 f2 00 0c     movt    r12, #0
+// CHECK-NEXT:     1010:       fc 44   add     r12, pc
+// CHECK-NEXT:     1012:       60 47   bx      r12
+// CHECK-NEXT:     1014:       40 f2 24 0c     movw    r12, #36
+// CHECK-NEXT:     1018:       c0 f2 00 0c     movt    r12, #0
+// CHECK-NEXT:     101c:       fc 44   add     r12, pc
+// CHECK-NEXT:     101e:       60 47   bx      r12
+
+// PLT: Disassembly of section .plt:
+// PLT-NEXT: .plt:
+// PLT:          1020:       04 e0 2d e5     str     lr, [sp, #-4]!
+// PLT-NEXT:     1024:       04 e0 9f e5     ldr     lr, [pc, #4]
+// PLT-NEXT:     1028:       0e e0 8f e0     add     lr, pc, lr
+// PLT-NEXT:     102c:       08 f0 be e5     ldr     pc, [lr, #8]!
+// PLT-NEXT:     1030:       d0 1f 00 00
+// PLT-NEXT:     1034:       04 c0 9f e5     ldr     r12, [pc, #4]
+// PLT-NEXT:     1038:       0f c0 8c e0     add     r12, r12, pc
+// PLT-NEXT:     103c:       00 f0 9c e5     ldr     pc, [r12]
+// PLT-NEXT:     1040:       cc 1f 00 00
+// PLT-NEXT:     1044:       04 c0 9f e5     ldr     r12, [pc, #4]
+// PLT-NEXT:     1048:       0f c0 8c e0     add     r12, r12, pc
+// PLT-NEXT:     104c:       00 f0 9c e5     ldr     pc, [r12]
+// PLT-NEXT:     1050:       c0 1f 00 00




More information about the llvm-commits mailing list