[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