[lld] r274863 - Recommit R274836 Add Thunk support framework for ARM and Mips
Peter Collingbourne via llvm-commits
llvm-commits at lists.llvm.org
Fri Jul 8 12:12:28 PDT 2016
Hi Peter, it looks like your change caused a bot failure:
http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-fast/builds/14493
Can you please take a look?
On Fri, Jul 8, 2016 at 9:10 AM, Peter Smith via llvm-commits <
llvm-commits at lists.llvm.org> wrote:
> Author: psmith
> Date: Fri Jul 8 11:10:27 2016
> New Revision: 274863
>
> URL: http://llvm.org/viewvc/llvm-project?rev=274863&view=rev
> Log:
> Recommit R274836 Add Thunk support framework for ARM and Mips
>
> The TinyPtrVector of const Thunk<ELFT>* in InputSections.h can cause
> build failures on certain compiler/library combinations when Thunk<ELFT>
> is not a complete type or is an abstract class. Fixed by making Thunk<ELFT>
> non Abstract.
>
> type or is an abstract class
>
> Added:
> lld/trunk/ELF/Thunks.cpp (with props)
> lld/trunk/ELF/Thunks.h (with props)
> lld/trunk/test/ELF/arm-thumb-interwork-thunk.s (with props)
> Modified:
> lld/trunk/ELF/CMakeLists.txt
> lld/trunk/ELF/InputSection.cpp
> lld/trunk/ELF/InputSection.h
> lld/trunk/ELF/Relocations.cpp
> lld/trunk/ELF/Relocations.h
> lld/trunk/ELF/Symbols.cpp
> lld/trunk/ELF/Symbols.h
> lld/trunk/ELF/Target.cpp
> lld/trunk/ELF/Target.h
> lld/trunk/test/ELF/arm-mov-relocs.s
>
> Modified: lld/trunk/ELF/CMakeLists.txt
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/CMakeLists.txt?rev=274863&r1=274862&r2=274863&view=diff
>
> ==============================================================================
> --- lld/trunk/ELF/CMakeLists.txt (original)
> +++ lld/trunk/ELF/CMakeLists.txt Fri Jul 8 11:10:27 2016
> @@ -21,6 +21,7 @@ add_lld_library(lldELF
> SymbolTable.cpp
> Symbols.cpp
> Target.cpp
> + Thunks.cpp
> Writer.cpp
>
> LINK_COMPONENTS
>
> Modified: lld/trunk/ELF/InputSection.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=274863&r1=274862&r2=274863&view=diff
>
> ==============================================================================
> --- lld/trunk/ELF/InputSection.cpp (original)
> +++ lld/trunk/ELF/InputSection.cpp Fri Jul 8 11:10:27 2016
> @@ -14,6 +14,7 @@
> #include "InputFiles.h"
> #include "OutputSections.h"
> #include "Target.h"
> +#include "Thunks.h"
>
> #include "llvm/Support/Compression.h"
> #include "llvm/Support/Endian.h"
> @@ -128,9 +129,9 @@ InputSectionBase<ELFT> *InputSection<ELF
> return Sections[this->Header->sh_info];
> }
>
> -template <class ELFT> void InputSection<ELFT>::addThunk(SymbolBody &Body)
> {
> - Body.ThunkIndex = Thunks.size();
> - Thunks.push_back(&Body);
> +template <class ELFT>
> +void InputSection<ELFT>::addThunk(const Thunk<ELFT> *T) {
> + Thunks.push_back(T);
> }
>
> template <class ELFT> uint64_t InputSection<ELFT>::getThunkOff() const {
> @@ -138,7 +139,10 @@ template <class ELFT> uint64_t InputSect
> }
>
> template <class ELFT> uint64_t InputSection<ELFT>::getThunksSize() const {
> - return Thunks.size() * Target->ThunkSize;
> + uint64_t Total = 0;
> + for (const Thunk<ELFT> *T : Thunks)
> + Total += T->size();
> + return Total;
> }
>
> // This is used for -r. We can't use memcpy to copy relocations because
> we need
> @@ -183,8 +187,11 @@ getSymVA(uint32_t Type, typename ELFT::u
> Out<ELFT>::Got->getNumEntries() * sizeof(uintX_t);
> case R_TLSLD_PC:
> return Out<ELFT>::Got->getTlsIndexVA() + A - P;
> - case R_THUNK:
> - return Body.getThunkVA<ELFT>();
> + case R_THUNK_ABS:
> + return Body.getThunkVA<ELFT>() + A;
> + case R_THUNK_PC:
> + case R_THUNK_PLT_PC:
> + return Body.getThunkVA<ELFT>() + A - P;
> case R_PPC_TOC:
> return getPPC64TocBase() + A;
> case R_TLSGD:
> @@ -404,9 +411,9 @@ template <class ELFT> void InputSection<
> // jump istruction.
> if (!Thunks.empty()) {
> Buf += OutSecOff + getThunkOff();
> - for (const SymbolBody *S : Thunks) {
> - Target->writeThunk(Buf, S->getVA<ELFT>());
> - Buf += Target->ThunkSize;
> + for (const Thunk<ELFT> *T : Thunks) {
> + T->writeTo(Buf);
> + Buf += T->size();
> }
> }
> }
>
> Modified: lld/trunk/ELF/InputSection.h
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.h?rev=274863&r1=274862&r2=274863&view=diff
>
> ==============================================================================
> --- lld/trunk/ELF/InputSection.h (original)
> +++ lld/trunk/ELF/InputSection.h Fri Jul 8 11:10:27 2016
> @@ -12,6 +12,7 @@
>
> #include "Config.h"
> #include "Relocations.h"
> +#include "Thunks.h"
> #include "lld/Core/LLVM.h"
> #include "llvm/ADT/DenseSet.h"
> #include "llvm/ADT/TinyPtrVector.h"
> @@ -208,8 +209,8 @@ public:
>
> // Register thunk related to the symbol. When the section is written
> // to a mmap'ed file, target is requested to write an actual thunk code.
> - // Now thunks is supported for MIPS target only.
> - void addThunk(SymbolBody &Body);
> + // Now thunks is supported for MIPS and ARM target only.
> + void addThunk(const Thunk<ELFT> *T);
>
> // The offset of synthetic thunk code from beginning of this section.
> uint64_t getThunkOff() const;
> @@ -230,7 +231,7 @@ private:
> // Used by ICF.
> uint64_t GroupId = 0;
>
> - llvm::TinyPtrVector<const SymbolBody *> Thunks;
> + llvm::TinyPtrVector<const Thunk<ELFT> *> Thunks;
> };
>
> // MIPS .reginfo section provides information on the registers used by
> the code
>
> Modified: lld/trunk/ELF/Relocations.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.cpp?rev=274863&r1=274862&r2=274863&view=diff
>
> ==============================================================================
> --- lld/trunk/ELF/Relocations.cpp (original)
> +++ lld/trunk/ELF/Relocations.cpp Fri Jul 8 11:10:27 2016
> @@ -46,6 +46,7 @@
> #include "OutputSections.h"
> #include "SymbolTable.h"
> #include "Target.h"
> +#include "Thunks.h"
>
> #include "llvm/Support/Endian.h"
> #include "llvm/Support/raw_ostream.h"
> @@ -276,14 +277,14 @@ template <class ELFT> static bool isAbso
>
> static bool needsPlt(RelExpr Expr) {
> return Expr == R_PLT_PC || Expr == R_PPC_PLT_OPD || Expr == R_PLT ||
> - Expr == R_PLT_PAGE_PC;
> + Expr == R_PLT_PAGE_PC || Expr == R_THUNK_PLT_PC;
> }
>
> // True if this expression is of the form Sym - X, where X is a position
> in the
> // file (PC, or GOT for example).
> static bool isRelExpr(RelExpr Expr) {
> return Expr == R_PC || Expr == R_GOTREL || Expr == R_PAGE_PC ||
> - Expr == R_RELAX_GOT_PC;
> + Expr == R_RELAX_GOT_PC || Expr == R_THUNK_PC || Expr ==
> R_THUNK_PLT_PC;
> }
>
> template <class ELFT>
> @@ -293,7 +294,8 @@ static bool isStaticLinkTimeConstant(Rel
> if (E == R_SIZE || E == R_GOT_FROM_END || E == R_GOT_OFF ||
> E == R_MIPS_GOT_LOCAL_PAGE || E == R_MIPS_GOT_OFF || E ==
> R_MIPS_TLSGD ||
> E == R_GOT_PAGE_PC || E == R_GOT_PC || E == R_PLT_PC || E ==
> R_TLSGD_PC ||
> - E == R_TLSGD || E == R_PPC_PLT_OPD || E == R_TLSDESC_PAGE || E ==
> R_HINT)
> + E == R_TLSGD || E == R_PPC_PLT_OPD || E == R_TLSDESC_PAGE ||
> + E == R_HINT || E == R_THUNK_PC || E == R_THUNK_PLT_PC)
> return true;
>
> // These never do, except if the entire file is position dependent or if
> @@ -402,8 +404,6 @@ template <class ELFT>
> static RelExpr adjustExpr(const elf::ObjectFile<ELFT> &File, SymbolBody
> &Body,
> bool IsWrite, RelExpr Expr, uint32_t Type,
> const uint8_t *Data) {
> - if (Target->needsThunk(Type, File, Body))
> - return R_THUNK;
> bool Preemptible = isPreemptible(Body, Type);
> if (Body.isGnuIFunc()) {
> Expr = toPlt(Expr);
> @@ -413,6 +413,7 @@ static RelExpr adjustExpr(const elf::Obj
> if (Expr == R_GOT_PC)
> Expr = Target->adjustRelaxExpr(Type, Data, Expr);
> }
> + Expr = Target->getThunkExpr(Expr, Type, File, Body);
>
> if (IsWrite || isStaticLinkTimeConstant<ELFT>(Expr, Type, Body))
> return Expr;
> @@ -556,7 +557,8 @@ static void scanRelocs(InputSectionBase<
> if (Expr == R_HINT)
> continue;
>
> - if (needsPlt(Expr) || Expr == R_THUNK || refersToGotEntry(Expr) ||
> + if (needsPlt(Expr) || Expr == R_THUNK_ABS || Expr == R_THUNK_PC ||
> + Expr == R_THUNK_PLT_PC || refersToGotEntry(Expr) ||
> !isPreemptible(Body, Type)) {
> // If the relocation points to something in the file, we can
> process it.
> bool Constant = isStaticLinkTimeConstant<ELFT>(Expr, Type, Body);
> @@ -600,14 +602,10 @@ static void scanRelocs(InputSectionBase<
>
> // 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.
> - if (Expr == R_THUNK) {
> - if (!Body.hasThunk()) {
> - auto *Sec = cast<InputSection<ELFT>>(
> - cast<DefinedRegular<ELFT>>(&Body)->Section);
> - Sec->addThunk(Body);
> - }
> - continue;
> + // 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);
> }
>
> // At this point we are done with the relocated position. Some
> relocations
>
> Modified: lld/trunk/ELF/Relocations.h
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.h?rev=274863&r1=274862&r2=274863&view=diff
>
> ==============================================================================
> --- lld/trunk/ELF/Relocations.h (original)
> +++ lld/trunk/ELF/Relocations.h Fri Jul 8 11:10:27 2016
> @@ -52,7 +52,9 @@ enum RelExpr {
> R_RELAX_TLS_IE_TO_LE,
> R_RELAX_TLS_LD_TO_LE,
> R_SIZE,
> - R_THUNK,
> + R_THUNK_ABS,
> + R_THUNK_PC,
> + R_THUNK_PLT_PC,
> R_TLS,
> R_TLSDESC,
> R_TLSDESC_PAGE,
>
> Modified: lld/trunk/ELF/Symbols.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.cpp?rev=274863&r1=274862&r2=274863&view=diff
>
> ==============================================================================
> --- lld/trunk/ELF/Symbols.cpp (original)
> +++ lld/trunk/ELF/Symbols.cpp Fri Jul 8 11:10:27 2016
> @@ -134,6 +134,14 @@ bool SymbolBody::isPreemptible() const {
> return true;
> }
>
> +template <class ELFT> bool SymbolBody::hasThunk() const {
> + if (auto *DR = dyn_cast<DefinedRegular<ELFT>>(this))
> + return DR->ThunkData != nullptr;
> + if (auto *S = dyn_cast<SharedSymbol<ELFT>>(this))
> + return S->ThunkData != nullptr;
> + return false;
> +}
> +
> template <class ELFT> InputFile *SymbolBody::getSourceFile() {
> if (auto *S = dyn_cast<DefinedRegular<ELFT>>(this))
> return S->Section ? S->Section->getFile() : nullptr;
> @@ -174,10 +182,11 @@ template <class ELFT> typename ELFT::uin
> }
>
> template <class ELFT> typename ELFT::uint SymbolBody::getThunkVA() const {
> - auto *D = cast<DefinedRegular<ELFT>>(this);
> - auto *S = cast<InputSection<ELFT>>(D->Section);
> - return S->OutSec->getVA() + S->OutSecOff + S->getThunkOff() +
> - ThunkIndex * Target->ThunkSize;
> + if (const auto *DR = dyn_cast<DefinedRegular<ELFT>>(this))
> + return DR->ThunkData->getVA();
> + if (const auto *S = dyn_cast<SharedSymbol<ELFT>>(this))
> + return S->ThunkData->getVA();
> + fatal("getThunkVA() not supported for Symbol class\n");
> }
>
> template <class ELFT> typename ELFT::uint SymbolBody::getSize() const {
> @@ -250,6 +259,10 @@ bool Symbol::includeInDynsym() const {
> return (ExportDynamic && VersionId != VER_NDX_LOCAL) ||
> body()->isShared() ||
> (body()->isUndefined() && Config->Shared);
> }
> +template bool SymbolBody::hasThunk<ELF32LE>() const;
> +template bool SymbolBody::hasThunk<ELF32BE>() const;
> +template bool SymbolBody::hasThunk<ELF64LE>() const;
> +template bool SymbolBody::hasThunk<ELF64BE>() const;
>
> template InputFile *SymbolBody::template getSourceFile<ELF32LE>();
> template InputFile *SymbolBody::template getSourceFile<ELF32BE>();
> @@ -276,6 +289,11 @@ template uint32_t SymbolBody::template g
> template uint64_t SymbolBody::template getGotPltVA<ELF64LE>() const;
> template uint64_t SymbolBody::template getGotPltVA<ELF64BE>() const;
>
> +template uint32_t SymbolBody::template getThunkVA<ELF32LE>() const;
> +template uint32_t SymbolBody::template getThunkVA<ELF32BE>() const;
> +template uint64_t SymbolBody::template getThunkVA<ELF64LE>() const;
> +template uint64_t SymbolBody::template getThunkVA<ELF64BE>() const;
> +
> template uint32_t SymbolBody::template getGotPltOffset<ELF32LE>() const;
> template uint32_t SymbolBody::template getGotPltOffset<ELF32BE>() const;
> template uint64_t SymbolBody::template getGotPltOffset<ELF64LE>() const;
> @@ -291,11 +309,6 @@ template uint32_t SymbolBody::template g
> template uint64_t SymbolBody::template getSize<ELF64LE>() const;
> template uint64_t SymbolBody::template getSize<ELF64BE>() const;
>
> -template uint32_t SymbolBody::template getThunkVA<ELF32LE>() const;
> -template uint32_t SymbolBody::template getThunkVA<ELF32BE>() const;
> -template uint64_t SymbolBody::template getThunkVA<ELF64LE>() const;
> -template uint64_t SymbolBody::template getThunkVA<ELF64BE>() const;
> -
> template class elf::DefinedSynthetic<ELF32LE>;
> template class elf::DefinedSynthetic<ELF32BE>;
> template class elf::DefinedSynthetic<ELF64LE>;
>
> Modified: lld/trunk/ELF/Symbols.h
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.h?rev=274863&r1=274862&r2=274863&view=diff
>
> ==============================================================================
> --- lld/trunk/ELF/Symbols.h (original)
> +++ lld/trunk/ELF/Symbols.h Fri Jul 8 11:10:27 2016
> @@ -84,11 +84,10 @@ public:
> uint32_t GotIndex = -1;
> uint32_t GotPltIndex = -1;
> uint32_t PltIndex = -1;
> - uint32_t ThunkIndex = -1;
> uint32_t GlobalDynIndex = -1;
> bool isInGot() const { return GotIndex != -1U; }
> bool isInPlt() const { return PltIndex != -1U; }
> - bool hasThunk() const { return ThunkIndex != -1U; }
> + template <class ELFT> bool hasThunk() const;
>
> template <class ELFT>
> typename ELFT::uint getVA(typename ELFT::uint Addend = 0) const;
> @@ -229,6 +228,10 @@ public:
> // If this is null, the symbol is an absolute symbol.
> InputSectionBase<ELFT> *&Section;
>
> + // If non-null the symbol has a Thunk that may be used as an alternative
> + // destination for callers of this Symbol.
> + std::unique_ptr<Thunk<ELFT>> ThunkData;
> +
> private:
> static InputSectionBase<ELFT> *NullInputSection;
> };
> @@ -301,6 +304,9 @@ public:
> // OffsetInBss is significant only when needsCopy() is true.
> uintX_t OffsetInBss = 0;
>
> + // If non-null the symbol has a Thunk that may be used as an alternative
> + // destination for callers of this Symbol.
> + std::unique_ptr<Thunk<ELFT>> ThunkData;
> bool needsCopy() const { return this->NeedsCopyOrPltAddr &&
> !this->isFunc(); }
> };
>
>
> Modified: lld/trunk/ELF/Target.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.cpp?rev=274863&r1=274862&r2=274863&view=diff
>
> ==============================================================================
> --- lld/trunk/ELF/Target.cpp (original)
> +++ lld/trunk/ELF/Target.cpp Fri Jul 8 11:10:27 2016
> @@ -29,6 +29,7 @@
> #include "InputFiles.h"
> #include "OutputSections.h"
> #include "Symbols.h"
> +#include "Thunks.h"
>
> #include "llvm/ADT/ArrayRef.h"
> #include "llvm/Object/ELF.h"
> @@ -181,6 +182,9 @@ 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,
> + const SymbolBody &S) const override;
> void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const
> override;
> };
>
> @@ -197,8 +201,9 @@ public:
> void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t
> PltEntryAddr,
> int32_t Index, unsigned RelOff) const override;
> void writeThunk(uint8_t *Buf, uint64_t S) const override;
> - bool needsThunk(uint32_t Type, const InputFile &File,
> - const SymbolBody &S) const override;
> + 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;
> };
> @@ -248,9 +253,10 @@ uint64_t TargetInfo::getVAStart() const
>
> bool TargetInfo::usesOnlyLowPageBits(uint32_t Type) const { return false;
> }
>
> -bool TargetInfo::needsThunk(uint32_t Type, const InputFile &File,
> - const SymbolBody &S) const {
> - return false;
> +RelExpr TargetInfo::getThunkExpr(RelExpr Expr, uint32_t RelocType,
> + const InputFile &File,
> + const SymbolBody &S) const {
> + return Expr;
> }
>
> bool TargetInfo::isTlsInitialExecRel(uint32_t Type) const { return false;
> }
> @@ -1483,8 +1489,12 @@ RelExpr ARMTargetInfo::getRelExpr(uint32
> // FIXME: currently B(S) assumed to be .got, this may not hold for all
> // platforms.
> return R_GOTONLY_PC;
> + case R_ARM_MOVW_PREL_NC:
> + case R_ARM_MOVT_PREL:
> case R_ARM_PREL31:
> case R_ARM_REL32:
> + case R_ARM_THM_MOVW_PREL_NC:
> + case R_ARM_THM_MOVT_PREL:
> return R_PC;
> }
> }
> @@ -1532,6 +1542,34 @@ void ARMTargetInfo::writePlt(uint8_t *Bu
> write32le(Buf + 12, GotEntryAddr - L1 - 8);
> }
>
> +RelExpr ARMTargetInfo::getThunkExpr(RelExpr Expr, uint32_t RelocType,
> + const InputFile &File,
> + const SymbolBody &S) const {
> + // 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
> + // R_ARM_THM_CALL.
> + switch (RelocType) {
> + case R_ARM_PC24:
> + case R_ARM_PLT32:
> + case R_ARM_JUMP24:
> + // Source is ARM, all PLT entries are ARM so no interworking required.
> + // Otherwise we need to interwork if Symbol has bit 0 set (Thumb).
> + if (Expr == R_PC && ((S.getVA<ELF32LE>() & 1) == 1))
> + return R_THUNK_PC;
> + break;
> + case R_ARM_THM_JUMP19:
> + case R_ARM_THM_JUMP24:
> + // Source is Thumb, all PLT entries are ARM so interworking is
> required.
> + // Otherwise we need to interwork if Symbol has bit 0 clear (ARM).
> + if (Expr == R_PLT_PC)
> + return R_THUNK_PLT_PC;
> + if ((S.getVA<ELF32LE>() & 1) == 0)
> + return R_THUNK_PC;
> + break;
> + }
> + return Expr;
> +}
> +
> void ARMTargetInfo::relocateOne(uint8_t *Loc, uint32_t Type,
> uint64_t Val) const {
> switch (Type) {
> @@ -1615,17 +1653,20 @@ void ARMTargetInfo::relocateOne(uint8_t
> ((Val >> 1) & 0x07ff)); // imm11
> break;
> case R_ARM_MOVW_ABS_NC:
> + case R_ARM_MOVW_PREL_NC:
> write32le(Loc, (read32le(Loc) & ~0x000f0fff) | ((Val & 0xf000) << 4) |
> (Val & 0x0fff));
> break;
> case R_ARM_MOVT_ABS:
> - checkUInt<32>(Val, Type);
> + case R_ARM_MOVT_PREL:
> + checkInt<32>(Val, Type);
> write32le(Loc, (read32le(Loc) & ~0x000f0fff) |
> (((Val >> 16) & 0xf000) << 4) | ((Val >> 16) &
> 0xfff));
> break;
> case R_ARM_THM_MOVT_ABS:
> + case R_ARM_THM_MOVT_PREL:
> // Encoding T1: A = imm4:i:imm3:imm8
> - checkUInt<32>(Val, Type);
> + checkInt<32>(Val, Type);
> write16le(Loc,
> 0xf2c0 | // opcode
> ((Val >> 17) & 0x0400) | // i
> @@ -1636,6 +1677,7 @@ void ARMTargetInfo::relocateOne(uint8_t
> ((Val >> 16) & 0x00ff)); // imm8
> break;
> case R_ARM_THM_MOVW_ABS_NC:
> + case R_ARM_THM_MOVW_PREL_NC:
> // Encoding T3: A = imm4:i:imm3:imm8
> write16le(Loc,
> 0xf240 | // opcode
> @@ -1682,8 +1724,8 @@ uint64_t ARMTargetInfo::getImplicitAdden
> ((Hi & 0x003f) << 12) | // imm6
> ((Lo & 0x07ff) << 1)); // imm11:0
> }
> - case R_ARM_THM_JUMP24:
> - case R_ARM_THM_CALL: {
> + case R_ARM_THM_CALL:
> + case R_ARM_THM_JUMP24: {
> // Encoding B T4, BL T1, BLX T2: A = S:I1:I2:imm10:imm11:0
> // I1 = NOT(J1 EOR S), I2 = NOT(J2 EOR S)
> // FIXME: I1 and I2 require v6T2ops
> @@ -1698,12 +1740,16 @@ uint64_t ARMTargetInfo::getImplicitAdden
> // ELF for the ARM Architecture 4.6.1.1 the implicit addend for MOVW and
> // MOVT is in the range -32768 <= A < 32768
> case R_ARM_MOVW_ABS_NC:
> - case R_ARM_MOVT_ABS: {
> + case R_ARM_MOVT_ABS:
> + case R_ARM_MOVW_PREL_NC:
> + case R_ARM_MOVT_PREL: {
> uint64_t Val = read32le(Buf) & 0x000f0fff;
> return SignExtend64<16>(((Val & 0x000f0000) >> 4) | (Val & 0x00fff));
> }
> case R_ARM_THM_MOVW_ABS_NC:
> - case R_ARM_THM_MOVT_ABS: {
> + case R_ARM_THM_MOVT_ABS:
> + case R_ARM_THM_MOVW_PREL_NC:
> + case R_ARM_THM_MOVT_PREL: {
> // Encoding T3: A = imm4:i:imm3:imm8
> uint16_t Hi = read16le(Buf);
> uint16_t Lo = read16le(Buf + 2);
> @@ -1720,7 +1766,6 @@ template <class ELFT> MipsTargetInfo<ELF
> PageSize = 65536;
> PltEntrySize = 16;
> PltHeaderSize = 32;
> - ThunkSize = 16;
> CopyRel = R_MIPS_COPY;
> PltRel = R_MIPS_JUMP_SLOT;
> if (ELFT::Is64Bits) {
> @@ -1887,28 +1932,31 @@ void MipsTargetInfo<ELFT>::writeThunk(ui
> }
>
> template <class ELFT>
> -bool MipsTargetInfo<ELFT>::needsThunk(uint32_t Type, const InputFile
> &File,
> - const SymbolBody &S) const {
> +RelExpr MipsTargetInfo<ELFT>::getThunkExpr(RelExpr Expr, uint32_t Type,
> + 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
> // we cannot make the jump directly and need to create a small stubs
> // to save the target function address.
> // See page 3-38
> ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
> if (Type != R_MIPS_26)
> - return false;
> + return Expr;
> auto *F = dyn_cast<ELFFileBase<ELFT>>(&File);
> if (!F)
> - return false;
> + return Expr;
> // If current file has PIC code, LA25 stub is not required.
> if (F->getObj().getHeader()->e_flags & EF_MIPS_PIC)
> - return false;
> + return Expr;
> auto *D = dyn_cast<DefinedRegular<ELFT>>(&S);
> if (!D || !D->Section)
> - return false;
> + return Expr;
> // LA25 is required if target file has PIC code
> // or target symbol is a PIC symbol.
> - return (D->Section->getFile()->getObj().getHeader()->e_flags &
> EF_MIPS_PIC) ||
> - (D->StOther & STO_MIPS_MIPS16) == STO_MIPS_PIC;
> + const ELFFile<ELFT> &DefFile = D->Section->getFile()->getObj();
> + bool PicFile = DefFile.getHeader()->e_flags & EF_MIPS_PIC;
> + bool PicSym = (D->StOther & STO_MIPS_MIPS16) == STO_MIPS_PIC;
> + return (PicFile || PicSym) ? R_THUNK_ABS : Expr;
> }
>
> template <class ELFT>
>
> Modified: lld/trunk/ELF/Target.h
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.h?rev=274863&r1=274862&r2=274863&view=diff
>
> ==============================================================================
> --- lld/trunk/ELF/Target.h (original)
> +++ lld/trunk/ELF/Target.h Fri Jul 8 11:10:27 2016
> @@ -48,11 +48,16 @@ public:
> // a dynamic relocation.
> virtual bool usesOnlyLowPageBits(uint32_t Type) const;
>
> - virtual bool needsThunk(uint32_t Type, const InputFile &File,
> - const SymbolBody &S) const;
> -
> + // Decide whether a Thunk is needed for the relocation from File
> + // targeting S. Returns one of:
> + // Expr if there is no Thunk required
> + // R_THUNK_ABS if thunk is required and expression is absolute
> + // 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 SymbolBody &S) const;
> virtual void writeThunk(uint8_t *Buf, uint64_t 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;
> virtual ~TargetInfo();
> @@ -87,8 +92,6 @@ public:
> // Set to 0 for variant 2
> unsigned TcbSize = 0;
>
> - uint32_t ThunkSize = 0;
> -
> virtual RelExpr adjustRelaxExpr(uint32_t Type, const uint8_t *Data,
> RelExpr Expr) const;
> virtual void relaxGot(uint8_t *Loc, uint64_t Val) const;
>
> Added: lld/trunk/ELF/Thunks.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Thunks.cpp?rev=274863&view=auto
>
> ==============================================================================
> --- lld/trunk/ELF/Thunks.cpp (added)
> +++ lld/trunk/ELF/Thunks.cpp Fri Jul 8 11:10:27 2016
> @@ -0,0 +1,251 @@
> +//===- Thunks.cpp
> --------------------------------------------------------===//
> +//
> +// The LLVM Linker
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
>
> +//===---------------------------------------------------------------------===//
> +//
> +// This file contains both the Target independent and Target specific
> Thunk
> +// classes
> +//
> +// A Thunk Object represents a single Thunk that will be written to an
> +// InputSection when the InputSection contents are written. The
> InputSection
> +// maintains a list of Thunks that it owns.
>
> +//===---------------------------------------------------------------------===//
> +
> +#include "Thunks.h"
> +#include "Error.h"
> +#include "InputFiles.h"
> +#include "InputSection.h"
> +#include "OutputSections.h"
> +#include "Symbols.h"
> +#include "Target.h"
> +
> +#include "llvm/Object/ELF.h"
> +#include "llvm/Support/ELF.h"
> +#include "llvm/Support/Endian.h"
> +
> +using namespace llvm;
> +using namespace llvm::object;
> +using namespace llvm::support::endian;
> +using namespace llvm::ELF;
> +
> +namespace lld {
> +namespace elf {
> +
> +template <class ELFT> Thunk<ELFT>::~Thunk() {}
> +
> +template <class ELFT>
> +Thunk<ELFT>::Thunk(const SymbolBody &D, const InputSection<ELFT> &O)
> + : Destination(D), Owner(O), Offset(O.getThunkOff() +
> O.getThunksSize()) {}
> +
> +template <class ELFT> typename ELFT::uint Thunk<ELFT>::getVA() const {
> + return Owner.OutSec->getVA() + Owner.OutSecOff + Offset;
> +}
> +
> +// ARM Target Thunks
> +template <class ELFT> static uint64_t getARMThunkDestVA(const SymbolBody
> &S) {
> + return S.isInPlt() ? S.getPltVA<ELFT>() : S.getVA<ELFT>();
> +}
> +
> +// Specific ARM Thunk implementations. The naming convention is:
> +// Source State, TargetState, Target Requirement, ABS or PI, Range
> +namespace {
> +template <class ELFT>
> +class ARMToThumbV7ABSLongThunk final : public Thunk<ELFT> {
> +public:
> + uint32_t size() const override { return 12; }
> +
> + void writeTo(uint8_t *Buf) const override {
> + const uint8_t ATData[] = {
> + 0x00, 0xc0, 0x00, 0xe3, // movw ip,:lower16:S
> + 0x00, 0xc0, 0x40, 0xe3, // movt ip,:upper16:S
> + 0x1c, 0xff, 0x2f, 0xe1, // bx ip
> + };
> + uint64_t S = getARMThunkDestVA<ELFT>(this->Destination);
> + memcpy(Buf, ATData, sizeof(ATData));
> + Target->relocateOne(Buf, R_ARM_MOVW_ABS_NC, S);
> + Target->relocateOne(Buf + 4, R_ARM_MOVT_ABS, S);
> + }
> +
> + ARMToThumbV7ABSLongThunk(const SymbolBody &Destination,
> + const InputSection<ELFT> &Owner)
> + : Thunk<ELFT>(Destination, Owner) {}
> +};
> +
> +template <class ELFT> class ARMToThumbV7PILongThunk final : public
> Thunk<ELFT> {
> +public:
> + uint32_t size() const override { return 16; }
> +
> + void writeTo(uint8_t *Buf) const override {
> + const uint8_t ATData[] = {
> + 0xf0, 0xcf, 0x0f, 0xe3, // P: movw ip,:lower16:S - (P + (L1-P)
> +8)
> + 0x00, 0xc0, 0x40, 0xe3, // movt ip,:upper16:S - (P + (L1-P+4)
> +8)
> + 0x0f, 0xc0, 0x8c, 0xe0, // L1: add ip, ip, pc
> + 0x1c, 0xff, 0x2f, 0xe1, // bx r12
> + };
> + uint64_t S = getARMThunkDestVA<ELFT>(this->Destination);
> + uint64_t P = this->getVA();
> + memcpy(Buf, ATData, sizeof(ATData));
> + Target->relocateOne(Buf, R_ARM_MOVW_PREL_NC, S - P - 16);
> + Target->relocateOne(Buf + 4, R_ARM_MOVT_PREL, S - P - 12);
> + }
> +
> + ARMToThumbV7PILongThunk(const SymbolBody &Destination,
> + const InputSection<ELFT> &Owner)
> + : Thunk<ELFT>(Destination, Owner) {}
> +};
> +
> +template <class ELFT>
> +class ThumbToARMV7ABSLongThunk final : public Thunk<ELFT> {
> +public:
> + uint32_t size() const override { return 10; }
> +
> + void writeTo(uint8_t *Buf) const override {
> + const uint8_t TAData[] = {
> + 0x40, 0xf2, 0x00, 0x0c, // movw ip, :lower16:S
> + 0xc0, 0xf2, 0x00, 0x0c, // movt ip, :upper16:S
> + 0x60, 0x47, // bx ip
> + };
> + uint64_t S = getARMThunkDestVA<ELFT>(this->Destination);
> + memcpy(Buf, TAData, sizeof(TAData));
> + Target->relocateOne(Buf, R_ARM_THM_MOVW_ABS_NC, S);
> + Target->relocateOne(Buf + 4, R_ARM_THM_MOVT_ABS, S);
> + }
> +
> + ThumbToARMV7ABSLongThunk(const SymbolBody &Destination,
> + const InputSection<ELFT> &Owner)
> + : Thunk<ELFT>(Destination, Owner) {}
> +};
> +
> +template <class ELFT> class ThumbToARMV7PILongThunk final : public
> Thunk<ELFT> {
> +public:
> + uint32_t size() const override { return 12; }
> +
> + void writeTo(uint8_t *Buf) const override {
> + const uint8_t TAData[] = {
> + 0x4f, 0xf6, 0xf4, 0x7c, // P: movw ip,:lower16:S - (P + (L1-P) +
> 4)
> + 0xc0, 0xf2, 0x00, 0x0c, // movt ip,:upper16:S - (P + (L1-P+4)
> + 4)
> + 0xfc, 0x44, // L1: add r12, pc
> + 0x60, 0x47, // bx r12
> + };
> + uint64_t S = getARMThunkDestVA<ELFT>(this->Destination);
> + uint64_t P = this->getVA();
> + memcpy(Buf, TAData, sizeof(TAData));
> + Target->relocateOne(Buf, R_ARM_THM_MOVW_PREL_NC, S - P - 12);
> + Target->relocateOne(Buf + 4, R_ARM_THM_MOVT_PREL, S - P - 8);
> + }
> +
> + ThumbToARMV7PILongThunk(const SymbolBody &Destination,
> + const InputSection<ELFT> &Owner)
> + : Thunk<ELFT>(Destination, Owner) {}
> +};
> +
> +// Mips Thunks
> +// Only the MIPS LA25 Thunk is supported, the implementation is delegated
> +// to the MipsTargetInfo class in Target.cpp
> +template <class ELFT> class MipsThunk : public Thunk<ELFT> {
> +public:
> + MipsThunk(const SymbolBody &Destination, const InputSection<ELFT>
> &Owner);
> + uint32_t size() const override;
> + void writeTo(uint8_t *Buf) const override;
> +};
> +
> +template <class ELFT>
> +MipsThunk<ELFT>::MipsThunk(const SymbolBody &Destination,
> + const InputSection<ELFT> &Owner)
> + : Thunk<ELFT>(Destination, Owner) {}
> +
> +template <class ELFT> uint32_t MipsThunk<ELFT>::size() const { return 16;
> }
> +
> +template <class ELFT> void MipsThunk<ELFT>::writeTo(uint8_t *Buf) const {
> + const SymbolBody &D = this->Destination;
> + uint64_t S = D.getVA<ELFT>();
> + Target->writeThunk(Buf, S);
> +}
> +}
> +
> +template <class ELFT>
> +static void addThunkARM(uint32_t RelocType, SymbolBody &S,
> + InputSection<ELFT> &IS) {
> + if (S.hasThunk<ELFT>())
> + // only one Thunk supported per symbol
> + return;
> +
> + bool NeedsPI = Config->Pic || Config->Pie || Config->Shared;
> + Thunk<ELFT> *thunk;
> + // ARM relocations need ARM to Thumb interworking Thunks, Thumb
> relocations
> + // need Thumb to ARM relocations. Use position independent Thunks if we
> + // require position independent code.
> + switch (RelocType) {
> + case R_ARM_PC24:
> + case R_ARM_PLT32:
> + case R_ARM_JUMP24:
> + if (NeedsPI)
> + thunk = new ARMToThumbV7PILongThunk<ELFT>(S, IS);
> + else
> + thunk = new ARMToThumbV7ABSLongThunk<ELFT>(S, IS);
> + break;
> + case R_ARM_THM_JUMP19:
> + case R_ARM_THM_JUMP24:
> + if (NeedsPI)
> + thunk = new ThumbToARMV7PILongThunk<ELFT>(S, IS);
> + else
> + thunk = new ThumbToARMV7ABSLongThunk<ELFT>(S, IS);
> + break;
> + default:
> + fatal("Unrecognised Relocation type\n");
> + }
> + // ARM Thunks are added to the same InputSection as the relocation. This
> + // isn't strictly necessary but it makes it more likely that a limited
> range
> + // branch can reach the Thunk, and it makes Thunks to the PLT section
> easier
> + IS.addThunk(thunk);
> + if (DefinedRegular<ELFT> *DR = dyn_cast<DefinedRegular<ELFT>>(&S))
> + DR->ThunkData.reset(thunk);
> + else if (SharedSymbol<ELFT> *SH = dyn_cast<SharedSymbol<ELFT>>(&S))
> + SH->ThunkData.reset(thunk);
> + else
> + fatal("symbol not DefinedRegular or Shared\n");
> +}
> +
> +template <class ELFT>
> +static void addThunkMips(uint32_t RelocType, SymbolBody &S) {
> + if (S.hasThunk<ELFT>())
> + // only one Thunk supported per symbol
> + return;
> + // Mips Thunks are added to the InputSection defining S
> + auto *R = cast<DefinedRegular<ELFT>>(&S);
> + auto *Sec = cast<InputSection<ELFT>>(R->Section);
> + auto *T = new MipsThunk<ELFT>(S, *Sec);
> + Sec->addThunk(T);
> + R->ThunkData.reset(T);
> +}
> +
> +template <class ELFT>
> +void addThunk(uint32_t RelocType, SymbolBody &S, InputSection<ELFT> &IS) {
> + if (Config->EMachine == EM_ARM)
> + addThunkARM<ELFT>(RelocType, S, IS);
> + else if (Config->EMachine == EM_MIPS)
> + addThunkMips<ELFT>(RelocType, S);
> + else
> + llvm_unreachable("add Thunk only supported for ARM and Mips");
> +}
> +
> +template void addThunk<ELF32LE>(uint32_t, SymbolBody &,
> + InputSection<ELF32LE> &);
> +template void addThunk<ELF32BE>(uint32_t, SymbolBody &,
> + InputSection<ELF32BE> &);
> +template void addThunk<ELF64LE>(uint32_t, SymbolBody &,
> + InputSection<ELF64LE> &);
> +template void addThunk<ELF64BE>(uint32_t, SymbolBody &,
> + InputSection<ELF64BE> &);
> +
> +template uint32_t Thunk<ELF32LE>::getVA() const;
> +template uint32_t Thunk<ELF32BE>::getVA() const;
> +template uint64_t Thunk<ELF64LE>::getVA() const;
> +template uint64_t Thunk<ELF64BE>::getVA() const;
> +
> +} // namespace elf
> +} // namespace lld
>
> Propchange: lld/trunk/ELF/Thunks.cpp
>
> ------------------------------------------------------------------------------
> svn:eol-style = native
>
> Propchange: lld/trunk/ELF/Thunks.cpp
>
> ------------------------------------------------------------------------------
> svn:keywords = Rev Date Author URL Id
>
> Added: lld/trunk/ELF/Thunks.h
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Thunks.h?rev=274863&view=auto
>
> ==============================================================================
> --- lld/trunk/ELF/Thunks.h (added)
> +++ lld/trunk/ELF/Thunks.h Fri Jul 8 11:10:27 2016
> @@ -0,0 +1,55 @@
> +//===- Thunks.h
> --------------------------------------------------------===//
> +//
> +// The LLVM Linker
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
>
> +//===----------------------------------------------------------------------===//
> +
> +#ifndef LLD_ELF_THUNKS_H
> +#define LLD_ELF_THUNKS_H
> +
> +#include "Relocations.h"
> +
> +namespace lld {
> +namespace elf {
> +class SymbolBody;
> +class InputFile;
> +template <class ELFT> class InputSection;
> +template <class ELFT> class InputSectionBase;
> +
> +// Class to describe an instance of a Thunk.
> +// A Thunk is a code-sequence inserted by the linker in between a caller
> and
> +// the callee. The relocation to the callee is redirected to the Thunk,
> which
> +// after executing transfers control to the callee. Typical uses of Thunks
> +// include transferring control from non-pi to pi and changing state on
> +// targets like ARM.
> +//
> +// Thunks can be created for DefinedRegular and Shared Symbols. The Thunk
> +// is stored in a field of the Symbol Destination.
> +// Thunks to be written to an InputSection are recorded by the
> InputSection.
> +template <class ELFT> class Thunk {
> +public:
> + virtual uint32_t size() const { return 0; }
> + typename ELFT::uint getVA() const;
> + virtual void writeTo(uint8_t *Buf) const {};
> + Thunk(const SymbolBody &Destination, const InputSection<ELFT> &Owner);
> + virtual ~Thunk();
> +
> +protected:
> + const SymbolBody &Destination;
> + const InputSection<ELFT> &Owner;
> + uint64_t Offset;
> +};
> +
> +// For a Relocation to symbol S from InputSection Src, create a Thunk and
> +// update the fields of S and the InputSection that the Thunk body will be
> +// written to. At present there are implementations for ARM and Mips
> Thunks.
> +template <class ELFT>
> +void addThunk(uint32_t RelocType, SymbolBody &S, InputSection<ELFT> &Src);
> +
> +} // namespace elf
> +} // namespace lld
> +
> +#endif
>
> Propchange: lld/trunk/ELF/Thunks.h
>
> ------------------------------------------------------------------------------
> svn:eol-style = native
>
> Propchange: lld/trunk/ELF/Thunks.h
>
> ------------------------------------------------------------------------------
> svn:keywords = Rev Date Author URL Id
>
> Modified: lld/trunk/test/ELF/arm-mov-relocs.s
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/arm-mov-relocs.s?rev=274863&r1=274862&r2=274863&view=diff
>
> ==============================================================================
> --- lld/trunk/test/ELF/arm-mov-relocs.s (original)
> +++ lld/trunk/test/ELF/arm-mov-relocs.s Fri Jul 8 11:10:27 2016
> @@ -41,16 +41,53 @@ _start:
> // CHECK: movt r3, #2
> // CHECK: movt r4, #3
>
> +.section .R_ARM_MOVW_PREL_NC, "ax",%progbits
> + movw r0, :lower16:label - .
> + movw r1, :lower16:label1 - .
> + movw r2, :lower16:label2 + 4 - .
> + movw r3, :lower16:label3 - .
> + movw r4, :lower16:label3 + 0x103c - .
> +// 0x20000 - 0x11028 = :lower16:0xefd8 (61400)
> +// CHECK: 11028: {{.*}} movw r0, #61400
> +// 0x20004 = 0x1102c = :lower16:0xefd8 (61400)
> +// CHECK: 1102c: {{.*}} movw r1, #61400
> +// 0x20008 - 0x11030 + 4 = :lower16:0xefdc (61404)
> +// CHECK: 11030: {{.*}} movw r2, #61404
> +// 0x2fffc - 0x11034 = :lower16:0x1efc8 (61384)
> +// CHECK: 11034: {{.*}} movw r3, #61384
> +// 0x2fffc - 0x11038 +0x103c :lower16:0x20000 (0)
> +// CHECK: 11038: {{.*}} movw r4, #0
> +
> +.section .R_ARM_MOVT_PREL, "ax",%progbits
> + movt r0, :upper16:label - .
> + movt r1, :upper16:label1 - .
> + movt r2, :upper16:label2 + 0x4 - .
> + movt r3, :upper16:label3 - .
> + movt r4, :upper16:label3 + 0x1050 - .
> +// 0x20000 - 0x1103c = :upper16:0xefc4 = 0
> +// CHECK: 1103c: {{.*}} movt r0, #0
> +// 0x20004 - 0x11040 = :upper16:0xefc0 = 0
> +// CHECK: 11040: {{.*}} movt r1, #0
> +// 0x20008 - 0x11044 + 4 = :upper16:0xefc8 = 0
> +// CHECK: 11044: {{.*}} movt r2, #0
> +// 0x2fffc - 0x11048 = :upper16:0x1efb4 = 1
> +// CHECK: 11048: {{.*}} movt r3, #1
> +// 0x2fffc - 0x1104c + 0x1050 = :upper16:0x20000 = 2
> +// CHECK: 1104c: {{.*}} movt r4, #2
> .section .destination, "aw",%progbits
> .balign 65536
> +// 0x20000
> label:
> .word 0
> +// 0x20004
> label1:
> .word 1
> +// 0x20008
> label2:
> .word 2
> // Test label3 is immediately below 2^16 alignment boundary
> .space 65536 - 16
> +// 0x2fffc
> label3:
> .word 3
> // label3 + 4 is on a 2^16 alignment boundary
>
> Added: lld/trunk/test/ELF/arm-thumb-interwork-thunk.s
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/arm-thumb-interwork-thunk.s?rev=274863&view=auto
>
> ==============================================================================
> --- lld/trunk/test/ELF/arm-thumb-interwork-thunk.s (added)
> +++ lld/trunk/test/ELF/arm-thumb-interwork-thunk.s Fri Jul 8 11:10:27 2016
> @@ -0,0 +1,375 @@
> +// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t
> +// RUN: echo "SECTIONS { \
> +// RUN: .R_ARM_JUMP24_callee_1 : { *(.R_ARM_JUMP24_callee_low) } \
> +// RUN: .R_ARM_THM_JUMP_callee_1 : { *(.R_ARM_THM_JUMP_callee_low)}
> \
> +// RUN: .text : { *(.text) } \
> +// RUN: .arm_caller : { *(.arm_caller) } \
> +// RUN: .thumb_caller : { *(.thumb_caller) } \
> +// RUN: .R_ARM_JUMP24_callee_2 : { *(.R_ARM_JUMP24_callee_high) } \
> +// RUN: .R_ARM_THM_JUMP_callee_2 : { *(.R_ARM_THM_JUMP_callee_high)
> } } " > %t.script
> +// RUN: ld.lld --script %t.script %t -o %t2 2>&1
> +// RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi %t2 |
> FileCheck -check-prefix=CHECK-THUMB -check-prefix=CHECK-ABS-THUMB %s
> +// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t2 | FileCheck
> -check-prefix=CHECK-ARM -check-prefix=CHECK-ABS-ARM %s
> +// RUN: ld.lld --script %t.script %t -pie -o %t3 2>&1
> +// RUN: ld.lld --script %t.script %t --shared -o %t4 2>&1
> +// RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi %t3 |
> FileCheck -check-prefix=CHECK-THUMB -check-prefix=CHECK-PI-THUMB %s
> +// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t3 | FileCheck
> -check-prefix=CHECK-ARM -check-prefix=CHECK-PI-ARM %s
> +// RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi %t4 |
> FileCheck -check-prefix=CHECK-THUMB -check-prefix=CHECK-PI-PLT-THUMB %s
> +// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t4 | FileCheck
> -check-prefix=CHECK-ARM -check-prefix=CHECK-PI-PLT-ARM %s
> +// RUN: llvm-readobj -s -r %t4 | FileCheck -check-prefix=CHECK-DSO-REL %s
> +// REQUIRES: arm
> +
> +// Test ARM Thumb Interworking
> +// The file is linked and checked 3 times to check the following contexts
> +// - Absolute executables, absolute Thunks are used.
> +// - Position independent executables, position independent Thunks are
> used.
> +// - Shared object, position independent Thunks to PLT entries are used.
> +
> + .syntax unified
> +
> +// Target Sections for thunks at a lower address than the callers.
> +.section .R_ARM_JUMP24_callee_low, "ax", %progbits
> + .thumb
> + .balign 0x1000
> + .globl thumb_callee1
> + .type thumb_callee1, %function
> +thumb_callee1:
> + bx lr
> +
> +// CHECK-THUMB: Disassembly of section .R_ARM_JUMP24_callee_1:
> +// CHECK-THUMB: thumb_callee1:
> +// CHECK-THUMB: 1000: 70 47 bx
> + .section .R_ARM_THM_JUMP_callee_low, "ax", %progbits
> + .arm
> + .balign 0x100
> + .globl arm_callee1
> + .type arm_callee1, %function
> +arm_callee1:
> + bx lr
> +// Disassembly of section .R_ARM_THM_JUMP_callee_1:
> +// CHECK-ARM: arm_callee1:
> +// CHECK-ARM-NEXT: 1100: 1e ff 2f e1 bx lr
> +
> + // Calling sections
> + // At present ARM and Thumb interworking thunks are always added to the
> calling
> + // section.
> + .section .arm_caller, "ax", %progbits
> + .arm
> + .balign 0x100
> + .globl arm_caller
> + .type arm_caller, %function
> +arm_caller:
> + // If target supports BLX and target is in range we don't need an
> + // interworking thunk for a BL or BLX instruction.
> + bl thumb_callee1
> + blx thumb_callee1
> + // A B instruction can't be transformed into a BLX and needs an
> interworking
> + // thunk
> + b thumb_callee1
> + // As long as the thunk is in range it can be reused
> + b thumb_callee1
> + // There can be more than one thunk associated with a section
> + b thumb_callee2
> + b thumb_callee3
> + // In range ARM targets do not require interworking thunks
> + b arm_callee1
> + beq arm_callee2
> + bne arm_callee3
> + bx lr
> +// CHECK-ABS-ARM: Disassembly of section .arm_caller:
> +// CHECK-ABS-ARM-NEXT: arm_caller:
> +// CHECK-ABS-ARM-NEXT: 1300: 3e ff ff fa blx #-776
> <thumb_callee1>
> +// CHECK-ABS-ARM-NEXT: 1304: 3d ff ff fa blx #-780
> <thumb_callee1>
> +// CHECK-ABS-ARM-NEXT: 1308: 06 00 00 ea b #24
> <arm_caller+0x28>
> +// CHECK-ABS-ARM-NEXT: 130c: 05 00 00 ea b #20
> <arm_caller+0x28>
> +// CHECK-ABS-ARM-NEXT: 1310: 07 00 00 ea b #28
> <arm_caller+0x34>
> +// CHECK-ABS-ARM-NEXT: 1314: 09 00 00 ea b #36
> <arm_caller+0x40>
> +// CHECK-ABS-ARM-NEXT: 1318: 78 ff ff ea b #-544
> <arm_callee1>
> +// CHECK-ABS-ARM-NEXT: 131c: b7 00 00 0a beq #732
> <arm_callee2>
> +// CHECK-ABS-ARM-NEXT: 1320: b7 00 00 1a bne #732
> <arm_callee3>
> +// CHECK-ABS-ARM-NEXT: 1324: 1e ff 2f e1 bx lr
> +// 0x1001 = thumb_callee1
> +// CHECK-ABS-ARM-NEXT: 1328: 01 c0 01 e3 movw r12, #4097
> +// CHECK-ABS-ARM-NEXT: 132c: 00 c0 40 e3 movt r12, #0
> +// CHECK-ABS-ARM-NEXT: 1330: 1c ff 2f e1 bx r12
> +// 0x1501 = thumb_callee2
> +// CHECK-ABS-ARM-NEXT: 1334: 01 c5 01 e3 movw r12, #5377
> +// CHECK-ABS-ARM-NEXT: 1338: 00 c0 40 e3 movt r12, #0
> +// CHECK-ABS-ARM-NEXT: 133c: 1c ff 2f e1 bx r12
> +// 0x1503 = thumb_callee3
> +// CHECK-ABS-ARM-NEXT: 1340: 03 c5 01 e3 movw r12, #5379
> +// CHECK-ABS-ARM-NEXT: 1344: 00 c0 40 e3 movt r12, #0
> +// CHECK-ABS-ARM-NEXT: 1348: 1c ff 2f e1 bx r12
> +
> +// CHECK-PI-ARM: Disassembly of section .arm_caller:
> +// CHECK-PI-ARM-NEXT: arm_caller:
> +// CHECK-PI-ARM-NEXT: 1300: 3e ff ff fa blx #-776
> <thumb_callee1>
> +// CHECK-PI-ARM-NEXT: 1304: 3d ff ff fa blx #-780
> <thumb_callee1>
> +// 0x1308 + 8 + 0x18 = 0x1328
> +// CHECK-PI-ARM-NEXT: 1308: 06 00 00 ea b #24
> <arm_caller+0x28>
> +// 0x130c + 8 + 0x14 = 0x1328
> +// CHECK-PI-ARM-NEXT: 130c: 05 00 00 ea b #20
> <arm_caller+0x28>
> +// 0x1310 + 8 + 0x20 = 0x1338
> +// CHECK-PI-ARM-NEXT: 1310: 08 00 00 ea b #32
> <arm_caller+0x38>
> +// 0x1314 + 8 + 0x2c = 0x1348
> +// CHECK-PI-ARM-NEXT: 1314: 0b 00 00 ea b #44
> <arm_caller+0x48>
> +// CHECK-PI-ARM-NEXT: 1318: 78 ff ff ea b #-544
> <arm_callee1>
> +// CHECK-PI-ARM-NEXT: 131c: b7 00 00 0a beq #732
> <arm_callee2>
> +// CHECK-PI-ARM-NEXT: 1320: b7 00 00 1a bne #732
> <arm_callee3>
> +// CHECK-PI-ARM-NEXT: 1324: 1e ff 2f e1 bx lr
> +// 0x1330 + 8 - 0x337 = 0x1001 = thumb_callee1
> +// CHECK-PI-ARM-NEXT: 1328: c9 cc 0f e3 movw r12, #64713
> +// CHECK-PI-ARM-NEXT: 132c: ff cf 4f e3 movt r12, #65535
> +// CHECK-PI-ARM-NEXT: 1330: 0f c0 8c e0 add r12, r12, pc
> +// CHECK-PI-ARM-NEXT: 1334: 1c ff 2f e1 bx r12
> +// 0x1340 + 8 + 0x1b9 = 0x1501
> +// CHECK-PI-ARM-NEXT: 1338: b9 c1 00 e3 movw r12, #441
> +// CHECK-PI-ARM-NEXT: 133c: 00 c0 40 e3 movt r12, #0
> +// CHECK-PI-ARM-NEXT: 1340: 0f c0 8c e0 add r12, r12, pc
> +// CHECK-PI-ARM-NEXT: 1344: 1c ff 2f e1 bx r12
> +// 1350 + 8 + 0x1ab = 0x1503
> +// CHECK-PI-ARM-NEXT: 1348: ab c1 00 e3 movw r12, #427
> +// CHECK-PI-ARM-NEXT: 134c: 00 c0 40 e3 movt r12, #0
> +// CHECK-PI-ARM-NEXT: 1350: 0f c0 8c e0 add r12, r12, pc
> +// CHECK-PI-ARM-NEXT: 1354: 1c ff 2f e1 bx r12
> +
> +// All PLT entries are ARM, no need for interworking thunks
> +// CHECK-PI-ARM-PLT: Disassembly of section .arm_caller:
> +// CHECK-PI-ARM-PLT-NEXT: arm_caller:
> +// 0x17e4 PLT(thumb_callee1)
> +// CHECK-PI-ARM-PLT-NEXT: 1300: 37 01 00 eb bl #1244
> +// 0x17e4 PLT(thumb_callee1)
> +// CHECK-PI-ARM-PLT-NEXT: 1304: 36 01 00 eb bl #1240
> +// 0x17e4 PLT(thumb_callee1)
> +// CHECK-PI-ARM-PLT-NEXT: 1308: 35 01 00 ea b #1236
> +// 0x17e4 PLT(thumb_callee1)
> +// CHECK-PI-ARM-PLT-NEXT: 130c: 34 01 00 ea b #1232
> +// 0x17f4 PLT(thumb_callee2)
> +// CHECK-PI-ARM-PLT-NEXT: 1310: 37 01 00 ea b #1244
> +// 0x1804 PLT(thumb_callee3)
> +// CHECK-PI-ARM-PLT-NEXT: 1314: 3a 01 00 ea b #1256
> +// 0x1814 PLT(arm_callee1)
> +// CHECK-PI-ARM-PLT-NEXT: 1318: 3d 01 00 ea b #1268
> +// 0x1824 PLT(arm_callee2)
> +// CHECK-PI-ARM-PLT-NEXT: 131c: 40 01 00 0a beq #1280
> +// 0x1834 PLT(arm_callee3)
> +// CHECK-PI-ARM-PLT-NEXT: 1320: 43 01 00 1a bne #1292
> +// CHECK-PI-ARM-PLT-NEXT: 1324: 1e ff 2f e1 bx lr
> +
> + .section .thumb_caller, "ax", %progbits
> + .balign 0x100
> + .thumb
> + .globl thumb_caller
> + .type thumb_caller, %function
> +thumb_caller:
> + // If target supports BLX and target is in range we don't need an
> + // interworking thunk for a BL or BLX instruction.
> + bl arm_callee1
> + blx arm_callee1
> + // A B instruction can't be transformed into a BLX and needs an
> interworking
> + // thunk
> + b.w arm_callee1
> + // As long as the thunk is in range it can be reused
> + b.w arm_callee2
> + // There can be more than one thunk associated with a section
> + b.w arm_callee3
> + // Conditional branches also require interworking thunks, they can use
> the
> + // same interworking thunks.
> + beq.w arm_callee1
> + beq.w arm_callee2
> + bne.w arm_callee3
> +// CHECK-ABS-THUMB: Disassembly of section .thumb_caller:
> +// CHECK-ABS-THUMB-NEXT: thumb_caller:
> +// 0x1400 + 4 - 0x304 = 0x1100 = arm_callee1
> +// CHECK-ABS-THUMB-NEXT: 1400: ff f7 7e ee blx #-772
> +// 0x1404 + 4 - 0x308 = 0x1100 = arm_callee1
> +// CHECK-ABS-THUMB-NEXT: 1404: ff f7 7c ee blx #-776
> +// 0x1408 + 4 + 0x14 = 0x520
> +// CHECK-ABS-THUMB-NEXT: 1408: 00 f0 0a b8 b.w #20
> +// 0x140c + 4 + 0x1a = 0x52a
> +// CHECK-ABS-THUMB-NEXT: 140c: 00 f0 0d b8 b.w #26
> +// 0x1410 + 4 + 0x20 = 0x534
> +// CHECK-ABS-THUMB-NEXT: 1410: 00 f0 10 b8 b.w #32
> +// 0x1414 + 4 + 8 = 0x520
> +// CHECK-ABS-THUMB-NEXT: 1414: 00 f0 04 80 beq.w #8
> +// 0x1418 + 4 + 0xe = 0x52a
> +// CHECK-ABS-THUMB-NEXT: 1418: 00 f0 07 80 beq.w #14
> +// 0x141c + 4 + 0x14 = 0x534
> +// CHECK-ABS-THUMB-NEXT: 141c: 40 f0 0a 80 bne.w #20
> +// 0x1100 = arm_callee1
> +// CHECK-ABS-THUMB-NEXT: 1420: 41 f2 00 1c movw r12, #4352
> +// CHECK-ABS-THUMB-NEXT: 1424: c0 f2 00 0c movt r12, #0
> +// CHECK-ABS-THUMB-NEXT: 1428: 60 47 bx r12
> +// 0x1600 = arm_callee2
> +// CHECK-ABS-THUMB-NEXT: 142a: 41 f2 00 6c movw r12, #5632
> +// CHECK-ABS-THUMB-NEXT: 142e: c0 f2 00 0c movt r12, #0
> +// CHECK-ABS-THUMB-NEXT: 1432: 60 47 bx r12
> +// 0x1604 = arm_callee3
> +// CHECK-ABS-THUMB-NEXT: 1434: 41 f2 04 6c movw r12, #5636
> +// CHECK-ABS-THUMB-NEXT: 1438: c0 f2 00 0c movt r12, #0
> +// CHECK-ABS-THUMB-NEXT: 143c: 60 47 bx r12
> +
> +// CHECK-PI-THUMB: Disassembly of section .thumb_caller:
> +// CHECK-PI-THUMB-NEXT: thumb_caller:
> +// CHECK-PI-THUMB-NEXT: 1400: ff f7 7e ee blx #-772
> +// CHECK-PI-THUMB-NEXT: 1404: ff f7 7c ee blx #-776
> +// CHECK-PI-THUMB-NEXT: 1408: 00 f0 0a b8 b.w #20
> +// CHECK-PI-THUMB-NEXT: 140c: 00 f0 0e b8 b.w #28
> +// CHECK-PI-THUMB-NEXT: 1410: 00 f0 12 b8 b.w #36
> +// CHECK-PI-THUMB-NEXT: 1414: 00 f0 04 80 beq.w #8
> +// CHECK-PI-THUMB-NEXT: 1418: 00 f0 08 80 beq.w #16
> +// CHECK-PI-THUMB-NEXT: 141c: 40 f0 0c 80 bne.w #24
> +// 0x1428 + 4 - 0x32c = 0x1100 = arm_callee1
> +// CHECK-PI-THUMB-NEXT: 1420: 4f f6 d4 4c movw r12, #64724
> +// CHECK-PI-THUMB-NEXT: 1424: cf f6 ff 7c movt r12, #65535
> +// CHECK-PI-THUMB-NEXT: 1428: fc 44 add r12, pc
> +// CHECK-PI-THUMB-NEXT: 142a: 60 47 bx r12
> +// 0x1434 + 4 + 0x1c8 = 0x1600 = arm_callee2
> +// CHECK-PI-THUMB-NEXT: 142c: 40 f2 c8 1c movw r12, #456
> +// CHECK-PI-THUMB-NEXT: 1430: c0 f2 00 0c movt r12, #0
> +// CHECK-PI-THUMB-NEXT: 1434: fc 44 add r12, pc
> +// CHECK-PI-THUMB-NEXT: 1436: 60 47 bx r12
> +// 0x1440 + 4 + 0x1c0 = 0x1604 = arm_callee3
> +// CHECK-PI-THUMB-NEXT: 1438: 40 f2 c0 1c movw r12, #448
> +// CHECK-PI-THUMB-NEXT: 143c: c0 f2 00 0c movt r12, #0
> +// CHECK-PI-THUMB-NEXT: 1440: fc 44 add r12, pc
> +// CHECK-PI-THUMB-NEXT: 1442: 60 47 bx r12
> +
> +// CHECK-PI-THUMB-PLT: Disassembly of section .arm_caller:
> +// CHECK-PI-THUMB-PLT-NEXT: thumb_caller:
> +// 0x1400 + 4 + 0x410 = 0x1814 = PLT(arm_callee1)
> +// CHECK-PI-THUMB-PLT-NEXT: 1400: 00 f0 08 ea blx #1040
> +// 0x1404 + 4 + 0x40c = 0x1814 = PLT(arm_callee1)
> +// CHECK-PI-THUMB-PLT-NEXT: 1404: 00 f0 06 ea blx #1036
> +// 0x1408 + 4 + 0x14 = 0x1420 = IWV(PLT(arm_callee1)
> +// CHECK-PI-THUMB-PLT-NEXT: 1408: 00 f0 0a b8 b.w #20
> +// 0x140c + 4 + 0x1c = 0x142c = IWV(PLT(arm_callee2)
> +// CHECK-PI-THUMB-PLT-NEXT: 140c: 00 f0 0e b8 b.w #28
> +// 0x1410 + 4 + 0x24 = 0x1438 = IWV(PLT(arm_callee3)
> +// CHECK-PI-THUMB-PLT-NEXT: 1410: 00 f0 12 b8 b.w #36
> +// 0x1414 + 4 + 8 = 0x1420 = IWV(PLT(arm_callee1)
> +// CHECK-PI-THUMB-PLT-NEXT: 1414: 00 f0 04 80 beq.w #8
> +// 0x1418 + 4 + 0x10 = 0x142c = IWV(PLT(arm_callee2)
> +// CHECK-PI-THUMB-PLT-NEXT: 1418: 00 f0 08 80 beq.w #16
> +// 0x141c + 4 + 0x18 = 0x1438 = IWV(PLT(arm_callee3)
> +// CHECK-PI-THUMB-PLT-NEXT: 141c: 40 f0 0c 80 bne.w #24
> +// 0x1428 + 4 + 0x3e8 = 0x1814 = PLT(arm_callee1)
> +// CHECK-PI-THUMB-PLT-NEXT: 1420: 40 f2 e8 3c movw r12, #1000
> +// CHECK-PI-THUMB-PLT-NEXT: 1424: c0 f2 00 0c movt r12, #0
> +// CHECK-PI-THUMB-PLT-NEXT: 1428: fc 44 add r12, pc
> +// CHECK-PI-THUMB-PLT-NEXT: 142a: 60 47 bx r12
> +// 0x1434 + 4 + 0x3ec = 0x1824 = PLT(arm_callee2)
> +// CHECK-PI-THUMB-PLT-NEXT: 142c: 40 f2 ec 3c movw r12, #1004
> +// CHECK-PI-THUMB-PLT-NEXT: 1430: c0 f2 00 0c movt r12, #0
> +// CHECK-PI-THUMB-PLT-NEXT: 1434: fc 44 add r12, pc
> +// CHECK-PI-THUMB-PLT-NEXT: 1436: 60 47 bx r12
> +// 0x1440 + 4 + 0x3f0 = 0x1834 = PLT(arm_callee3)
> +// CHECK-PI-THUMB-PLT-NEXT: 1438: 40 f2 f0 3c movw r12, #1008
> +// CHECK-PI-THUMB-PLT-NEXT: 143c: c0 f2 00 0c movt r12, #0
> +// CHECK-PI-THUMB-PLT-NEXT: 1440: fc 44 add r12, pc
> +// CHECK-PI-THUMB-PLT-NEXT: 1442: 60 47 bx r12
> +
> +// Target Sections for thunks at a higher address than the callers.
> +.section .R_ARM_JUMP24_callee_high, "ax", %progbits
> + .thumb
> + .balign 0x100
> + .globl thumb_callee2
> + .type thumb_callee2, %function
> +thumb_callee2:
> + bx lr
> +
> + .globl thumb_callee3
> + .type thumb_callee3, %function
> +thumb_callee3:
> + bx lr
> +// CHECK-THUMB: Disassembly of section .R_ARM_JUMP24_callee_2:
> +// CHECK-THUMB-NEXT: thumb_callee2:
> +// CHECK-THUMB-NEXT: 1500: 70 47 bx lr
> +// CHECK-THUMB: thumb_callee3:
> +// CHECK-THUMB-NEXT: 1502: 70 47 bx lr
> +
> + .section .R_ARM_THM_JUMP_callee_high, "ax", %progbits
> + .arm
> + .balign 0x100
> + .globl arm_callee2
> + .type arm_callee2, %function
> +arm_callee2:
> + bx lr
> + .globl arm_callee3
> + .type arm_callee3, %function
> +arm_callee3:
> + bx lr
> +// CHECK-ARM: Disassembly of section .R_ARM_THM_JUMP_callee_2:
> +// CHECK-ARM-NEXT: arm_callee2:
> +// CHECK-ARM-NEXT: 1600: 1e ff 2f e1 bx lr
> +// CHECK-ARM: arm_callee3:
> +// CHECK-ARM-NEXT: 1604: 1e ff 2f e1 bx lr
> +
> +// _start section just calls the arm and thumb calling sections
> + .text
> + .arm
> + .globl _start
> + .balign 0x100
> + .type _start, %function
> +_start:
> + bl arm_caller
> + bl thumb_caller
> + bx lr
> +
> +
> +// CHECK-PI-ARM-PLT: Disassembly of section .plt:
> +// CHECK-PI-ARM-PLT-NEXT: .plt:
> +// CHECK-PI-ARM-PLT-NEXT: 17b0: 04 e0 2d e5 str lr, [sp,
> #-4]!
> +// CHECK-PI-ARM-PLT-NEXT: 17b4: 04 e0 9f e5 ldr lr, [pc,
> #4]
> +// CHECK-PI-ARM-PLT-NEXT: 17b8: 0e e0 8f e0 add lr, pc, lr
> +// CHECK-PI-ARM-PLT-NEXT: 17bc: 08 f0 be e5 ldr pc, [lr,
> #8]!
> +// CHECK-PI-ARM-PLT-NEXT: 17c0: d4 00 00 00
> +// 0x17c8 + 8 + 0xd0 = 0x18a0 arm_caller
> +// CHECK-PI-ARM-PLT-NEXT: 17c4: 04 c0 9f e5 ldr r12, [pc,
> #4]
> +// CHECK-PI-ARM-PLT-NEXT: 17c8: 0f c0 8c e0 add r12, r12,
> pc
> +// CHECK-PI-ARM-PLT-NEXT: 17cc: 00 f0 9c e5 ldr pc, [r12]
> +// CHECK-PI-ARM-PLT-NEXT: 17d0: d0 00 00 00
> +// 0x17d8 + 8 + 0xc4 = 0x18a4 thumb_caller
> +// CHECK-PI-ARM-PLT-NEXT: 17d4: 04 c0 9f e5 ldr r12, [pc,
> #4]
> +// CHECK-PI-ARM-PLT-NEXT: 17d8: 0f c0 8c e0 add r12, r12,
> pc
> +// CHECK-PI-ARM-PLT-NEXT: 17dc: 00 f0 9c e5 ldr pc, [r12]
> +// CHECK-PI-ARM-PLT-NEXT: 17e0: c4 00 00 00
> +// 0x17e8 + 8 + 0xb8 = 0x18a8 thumb_callee1
> +// CHECK-PI-ARM-PLT-NEXT: 17e4: 04 c0 9f e5 ldr r12, [pc,
> #4]
> +// CHECK-PI-ARM-PLT-NEXT: 17e8: 0f c0 8c e0 add r12, r12,
> pc
> +// CHECK-PI-ARM-PLT-NEXT: 17ec: 00 f0 9c e5 ldr pc, [r12]
> +// CHECK-PI-ARM-PLT-NEXT: 17f0: b8 00 00 00
> +// 0x17f8 + 8 + 0xac = 0x18ac thumb_callee2
> +// CHECK-PI-ARM-PLT-NEXT: 17f4: 04 c0 9f e5 ldr r12, [pc,
> #4]
> +// CHECK-PI-ARM-PLT-NEXT: 17f8: 0f c0 8c e0 add r12, r12,
> pc
> +// CHECK-PI-ARM-PLT-NEXT: 17fc: 00 f0 9c e5 ldr pc, [r12]
> +// CHECK-PI-ARM-PLT-NEXT: 1800: ac 00 00 00
> +// 0x1808 + 8 + 0xa0 = 0x18b0 thumb_callee3
> +// CHECK-PI-ARM-PLT-NEXT: 1804: 04 c0 9f e5 ldr r12, [pc,
> #4]
> +// CHECK-PI-ARM-PLT-NEXT: 1808: 0f c0 8c e0 add r12, r12,
> pc
> +// CHECK-PI-ARM-PLT-NEXT: 180c: 00 f0 9c e5 ldr pc, [r12]
> +// CHECK-PI-ARM-PLT-NEXT: 1810: a0 00 00 00
> +// 0x1818 + 8 + 0x94 = 0x18b4 arm_callee1
> +// CHECK-PI-ARM-PLT-NEXT: 1814: 04 c0 9f e5 ldr r12, [pc,
> #4]
> +// CHECK-PI-ARM-PLT-NEXT: 1818: 0f c0 8c e0 add r12, r12,
> pc
> +// CHECK-PI-ARM-PLT-NEXT: 181c: 00 f0 9c e5 ldr pc, [r12]
> +// CHECK-PI-ARM-PLT-NEXT: 1820: 94 00 00 00
> +// 0x1828 + 8 + 0x88 = 0x18b8 arm_callee2
> +// CHECK-PI-ARM-PLT-NEXT: 1824: 04 c0 9f e5 ldr r12, [pc,
> #4]
> +// CHECK-PI-ARM-PLT-NEXT: 1828: 0f c0 8c e0 add r12, r12,
> pc
> +// CHECK-PI-ARM-PLT-NEXT: 182c: 00 f0 9c e5 ldr pc, [r12]
> +// CHECK-PI-ARM-PLT-NEXT: 1830: 88 00 00 00
> +// 0x1838 + 8 + 0x7c = 0x18bc arm_callee3
> +// CHECK-PI-ARM-PLT-NEXT: 1834: 04 c0 9f e5 ldr r12, [pc,
> #4]
> +// CHECK-PI-ARM-PLT-NEXT: 1838: 0f c0 8c e0 add r12, r12,
> pc
> +// CHECK-PI-ARM-PLT-NEXT: 183c: 00 f0 9c e5 ldr pc, [r12]
> +// CHECK-PI-ARM-PLT-NEXT: 1840: 7c 00 00 00
> +
> +// CHECK-DSO-REL: 0x18A0 R_ARM_JUMP_SLOT arm_caller
> +// CHECK-DSO-REL-NEXT: 0x18A4 R_ARM_JUMP_SLOT thumb_caller
> +// CHECK-DSO-REL-NEXT: 0x18A8 R_ARM_JUMP_SLOT thumb_callee1
> +// CHECK-DSO-REL-NEXT: 0x18AC R_ARM_JUMP_SLOT thumb_callee2
> +// CHECK-DSO-REL-NEXT: 0x18B0 R_ARM_JUMP_SLOT thumb_callee3
> +// CHECK-DSO-REL-NEXT: 0x18B4 R_ARM_JUMP_SLOT arm_callee1
> +// CHECK-DSO-REL-NEXT: 0x18B8 R_ARM_JUMP_SLOT arm_callee2
> +// CHECK-DSO-REL-NEXT: 0x18BC R_ARM_JUMP_SLOT arm_callee3
>
> Propchange: lld/trunk/test/ELF/arm-thumb-interwork-thunk.s
>
> ------------------------------------------------------------------------------
> svn:eol-style = native
>
> Propchange: lld/trunk/test/ELF/arm-thumb-interwork-thunk.s
>
> ------------------------------------------------------------------------------
> svn:keywords = Rev Date Author URL Id
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
--
--
Peter
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160708/77a81692/attachment-0001.html>
More information about the llvm-commits
mailing list