diff options
author | Peter Smith <peter.smith@linaro.org> | 2016-07-08 12:25:50 +0000 |
---|---|---|
committer | Peter Smith <peter.smith@linaro.org> | 2016-07-08 12:25:50 +0000 |
commit | eeb827447efb9ad349fb97214f07e8976d78eecd (patch) | |
tree | c5a8a29722f1132b601c6e116a37bc386c9fcc9b | |
parent | 0bdb5f971bc8e4c56ae7f9bd5a704170be81d22c (diff) | |
download | bcm5719-llvm-eeb827447efb9ad349fb97214f07e8976d78eecd.tar.gz bcm5719-llvm-eeb827447efb9ad349fb97214f07e8976d78eecd.zip |
Revert R274836 Add Thunk support framework for ARM and Mips
This seems to be causing a buildbot failure on lld-x86_64-freebsd. Will
reproduce locally and fix.
llvm-svn: 274841
-rw-r--r-- | lld/ELF/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lld/ELF/InputSection.cpp | 25 | ||||
-rw-r--r-- | lld/ELF/InputSection.h | 7 | ||||
-rw-r--r-- | lld/ELF/Relocations.cpp | 26 | ||||
-rw-r--r-- | lld/ELF/Relocations.h | 4 | ||||
-rw-r--r-- | lld/ELF/Symbols.cpp | 31 | ||||
-rw-r--r-- | lld/ELF/Symbols.h | 10 | ||||
-rw-r--r-- | lld/ELF/Target.cpp | 88 | ||||
-rw-r--r-- | lld/ELF/Target.h | 15 | ||||
-rw-r--r-- | lld/ELF/Thunks.cpp | 251 | ||||
-rw-r--r-- | lld/ELF/Thunks.h | 55 | ||||
-rw-r--r-- | lld/test/ELF/arm-mov-relocs.s | 37 | ||||
-rw-r--r-- | lld/test/ELF/arm-thumb-interwork-thunk.s | 375 |
13 files changed, 64 insertions, 861 deletions
diff --git a/lld/ELF/CMakeLists.txt b/lld/ELF/CMakeLists.txt index a1b65adc740..1875a1ebbcb 100644 --- a/lld/ELF/CMakeLists.txt +++ b/lld/ELF/CMakeLists.txt @@ -21,7 +21,6 @@ add_lld_library(lldELF SymbolTable.cpp Symbols.cpp Target.cpp - Thunks.cpp Writer.cpp LINK_COMPONENTS diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 97c273b42c4..3d3f34de93c 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -14,7 +14,6 @@ #include "InputFiles.h" #include "OutputSections.h" #include "Target.h" -#include "Thunks.h" #include "llvm/Support/Compression.h" #include "llvm/Support/Endian.h" @@ -129,9 +128,9 @@ InputSectionBase<ELFT> *InputSection<ELFT>::getRelocatedSection() { return Sections[this->Header->sh_info]; } -template <class ELFT> -void InputSection<ELFT>::addThunk(const Thunk<ELFT> *T) { - Thunks.push_back(T); +template <class ELFT> void InputSection<ELFT>::addThunk(SymbolBody &Body) { + Body.ThunkIndex = Thunks.size(); + Thunks.push_back(&Body); } template <class ELFT> uint64_t InputSection<ELFT>::getThunkOff() const { @@ -139,10 +138,7 @@ template <class ELFT> uint64_t InputSection<ELFT>::getThunkOff() const { } template <class ELFT> uint64_t InputSection<ELFT>::getThunksSize() const { - uint64_t Total = 0; - for (const Thunk<ELFT> *T : Thunks) - Total += T->size(); - return Total; + return Thunks.size() * Target->ThunkSize; } // This is used for -r. We can't use memcpy to copy relocations because we need @@ -187,11 +183,8 @@ getSymVA(uint32_t Type, typename ELFT::uint A, typename ELFT::uint P, Out<ELFT>::Got->getNumEntries() * sizeof(uintX_t); case R_TLSLD_PC: return Out<ELFT>::Got->getTlsIndexVA() + A - P; - 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_THUNK: + return Body.getThunkVA<ELFT>(); case R_PPC_TOC: return getPPC64TocBase() + A; case R_TLSGD: @@ -411,9 +404,9 @@ template <class ELFT> void InputSection<ELFT>::writeTo(uint8_t *Buf) { // jump istruction. if (!Thunks.empty()) { Buf += OutSecOff + getThunkOff(); - for (const Thunk<ELFT> *T : Thunks) { - T->writeTo(Buf); - Buf += T->size(); + for (const SymbolBody *S : Thunks) { + Target->writeThunk(Buf, S->getVA<ELFT>()); + Buf += Target->ThunkSize; } } } diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h index eabe5fb3c51..9c874d499fe 100644 --- a/lld/ELF/InputSection.h +++ b/lld/ELF/InputSection.h @@ -12,7 +12,6 @@ #include "Config.h" #include "Relocations.h" -#include "Thunks.h" #include "lld/Core/LLVM.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/TinyPtrVector.h" @@ -209,8 +208,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 and ARM target only. - void addThunk(const Thunk<ELFT> *T); + // Now thunks is supported for MIPS target only. + void addThunk(SymbolBody &Body); // The offset of synthetic thunk code from beginning of this section. uint64_t getThunkOff() const; @@ -231,7 +230,7 @@ private: // Used by ICF. uint64_t GroupId = 0; - llvm::TinyPtrVector<const Thunk<ELFT> *> Thunks; + llvm::TinyPtrVector<const SymbolBody *> Thunks; }; // MIPS .reginfo section provides information on the registers used by the code diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index e39eef7411d..a54c449c644 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -46,7 +46,6 @@ #include "OutputSections.h" #include "SymbolTable.h" #include "Target.h" -#include "Thunks.h" #include "llvm/Support/Endian.h" #include "llvm/Support/raw_ostream.h" @@ -277,14 +276,14 @@ template <class ELFT> static bool isAbsolute(const SymbolBody &Body) { 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_THUNK_PLT_PC; + Expr == R_PLT_PAGE_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_THUNK_PC || Expr == R_THUNK_PLT_PC; + Expr == R_RELAX_GOT_PC; } template <class ELFT> @@ -294,8 +293,7 @@ static bool isStaticLinkTimeConstant(RelExpr E, uint32_t Type, 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_THUNK_PC || E == R_THUNK_PLT_PC) + E == R_TLSGD || E == R_PPC_PLT_OPD || E == R_TLSDESC_PAGE || E == R_HINT) return true; // These never do, except if the entire file is position dependent or if @@ -404,6 +402,8 @@ 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,7 +413,6 @@ static RelExpr adjustExpr(const elf::ObjectFile<ELFT> &File, SymbolBody &Body, 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; @@ -557,8 +556,7 @@ static void scanRelocs(InputSectionBase<ELFT> &C, ArrayRef<RelTy> Rels) { if (Expr == R_HINT) continue; - if (needsPlt(Expr) || Expr == R_THUNK_ABS || Expr == R_THUNK_PC || - Expr == R_THUNK_PLT_PC || refersToGotEntry(Expr) || + if (needsPlt(Expr) || Expr == R_THUNK || 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); @@ -602,10 +600,14 @@ static void scanRelocs(InputSectionBase<ELFT> &C, ArrayRef<RelTy> Rels) { // 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); + // 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; } // At this point we are done with the relocated position. Some relocations diff --git a/lld/ELF/Relocations.h b/lld/ELF/Relocations.h index 4c1c74efb0d..bac52764bc5 100644 --- a/lld/ELF/Relocations.h +++ b/lld/ELF/Relocations.h @@ -52,9 +52,7 @@ enum RelExpr { R_RELAX_TLS_IE_TO_LE, R_RELAX_TLS_LD_TO_LE, R_SIZE, - R_THUNK_ABS, - R_THUNK_PC, - R_THUNK_PLT_PC, + R_THUNK, R_TLS, R_TLSDESC, R_TLSDESC_PAGE, diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp index 85c71e301c6..3e96b917719 100644 --- a/lld/ELF/Symbols.cpp +++ b/lld/ELF/Symbols.cpp @@ -134,14 +134,6 @@ 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; @@ -182,11 +174,10 @@ template <class ELFT> typename ELFT::uint SymbolBody::getPltVA() const { } template <class ELFT> typename ELFT::uint SymbolBody::getThunkVA() const { - 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"); + auto *D = cast<DefinedRegular<ELFT>>(this); + auto *S = cast<InputSection<ELFT>>(D->Section); + return S->OutSec->getVA() + S->OutSecOff + S->getThunkOff() + + ThunkIndex * Target->ThunkSize; } template <class ELFT> typename ELFT::uint SymbolBody::getSize() const { @@ -259,10 +250,6 @@ 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>(); @@ -289,11 +276,6 @@ template uint32_t SymbolBody::template getGotPltVA<ELF32BE>() const; 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; @@ -309,6 +291,11 @@ template uint32_t SymbolBody::template getSize<ELF32BE>() const; 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>; diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h index ec97b017fc2..e429f03e96e 100644 --- a/lld/ELF/Symbols.h +++ b/lld/ELF/Symbols.h @@ -84,10 +84,11 @@ 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; } - template <class ELFT> bool hasThunk() const; + bool hasThunk() const { return ThunkIndex != -1U; } template <class ELFT> typename ELFT::uint getVA(typename ELFT::uint Addend = 0) const; @@ -228,10 +229,6 @@ 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; }; @@ -304,9 +301,6 @@ 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(); } }; diff --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp index 51d18c370ba..58f3beb751a 100644 --- a/lld/ELF/Target.cpp +++ b/lld/ELF/Target.cpp @@ -29,7 +29,6 @@ #include "InputFiles.h" #include "OutputSections.h" #include "Symbols.h" -#include "Thunks.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/Object/ELF.h" @@ -182,9 +181,6 @@ 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; }; @@ -201,9 +197,8 @@ 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; - RelExpr getThunkExpr(RelExpr Expr, uint32_t RelocType, - const InputFile &File, - const SymbolBody &S) const override; + bool needsThunk(uint32_t Type, 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; }; @@ -253,10 +248,9 @@ uint64_t TargetInfo::getVAStart() const { return Config->Pic ? 0 : VAStart; } bool TargetInfo::usesOnlyLowPageBits(uint32_t Type) const { return false; } -RelExpr TargetInfo::getThunkExpr(RelExpr Expr, uint32_t RelocType, - const InputFile &File, - const SymbolBody &S) const { - return Expr; +bool TargetInfo::needsThunk(uint32_t Type, const InputFile &File, + const SymbolBody &S) const { + return false; } bool TargetInfo::isTlsInitialExecRel(uint32_t Type) const { return false; } @@ -1489,12 +1483,8 @@ RelExpr ARMTargetInfo::getRelExpr(uint32_t Type, const SymbolBody &S) const { // 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; } } @@ -1542,34 +1532,6 @@ void ARMTargetInfo::writePlt(uint8_t *Buf, uint64_t GotEntryAddr, 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) { @@ -1653,20 +1615,17 @@ void ARMTargetInfo::relocateOne(uint8_t *Loc, uint32_t Type, ((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: - case R_ARM_MOVT_PREL: - checkInt<32>(Val, Type); + checkUInt<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 - checkInt<32>(Val, Type); + checkUInt<32>(Val, Type); write16le(Loc, 0xf2c0 | // opcode ((Val >> 17) & 0x0400) | // i @@ -1677,7 +1636,6 @@ void ARMTargetInfo::relocateOne(uint8_t *Loc, uint32_t Type, ((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 @@ -1724,8 +1682,8 @@ uint64_t ARMTargetInfo::getImplicitAddend(const uint8_t *Buf, ((Hi & 0x003f) << 12) | // imm6 ((Lo & 0x07ff) << 1)); // imm11:0 } - case R_ARM_THM_CALL: - case R_ARM_THM_JUMP24: { + case R_ARM_THM_JUMP24: + case R_ARM_THM_CALL: { // 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 @@ -1740,16 +1698,12 @@ uint64_t ARMTargetInfo::getImplicitAddend(const uint8_t *Buf, // 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_MOVW_PREL_NC: - case R_ARM_MOVT_PREL: { + case R_ARM_MOVT_ABS: { 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_MOVW_PREL_NC: - case R_ARM_THM_MOVT_PREL: { + case R_ARM_THM_MOVT_ABS: { // Encoding T3: A = imm4:i:imm3:imm8 uint16_t Hi = read16le(Buf); uint16_t Lo = read16le(Buf + 2); @@ -1766,6 +1720,7 @@ template <class ELFT> MipsTargetInfo<ELFT>::MipsTargetInfo() { PageSize = 65536; PltEntrySize = 16; PltHeaderSize = 32; + ThunkSize = 16; CopyRel = R_MIPS_COPY; PltRel = R_MIPS_JUMP_SLOT; if (ELFT::Is64Bits) { @@ -1932,31 +1887,28 @@ void MipsTargetInfo<ELFT>::writeThunk(uint8_t *Buf, uint64_t S) const { } template <class ELFT> -RelExpr MipsTargetInfo<ELFT>::getThunkExpr(RelExpr Expr, uint32_t Type, - const InputFile &File, - const SymbolBody &S) const { +bool MipsTargetInfo<ELFT>::needsThunk(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 Expr; + return false; auto *F = dyn_cast<ELFFileBase<ELFT>>(&File); if (!F) - return Expr; + return false; // If current file has PIC code, LA25 stub is not required. if (F->getObj().getHeader()->e_flags & EF_MIPS_PIC) - return Expr; + return false; auto *D = dyn_cast<DefinedRegular<ELFT>>(&S); if (!D || !D->Section) - return Expr; + return false; // LA25 is required if target file has PIC code // or target symbol is a PIC symbol. - 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; + return (D->Section->getFile()->getObj().getHeader()->e_flags & EF_MIPS_PIC) || + (D->StOther & STO_MIPS_MIPS16) == STO_MIPS_PIC; } template <class ELFT> diff --git a/lld/ELF/Target.h b/lld/ELF/Target.h index 7adbf971a5c..822d38ae1fc 100644 --- a/lld/ELF/Target.h +++ b/lld/ELF/Target.h @@ -48,16 +48,11 @@ public: // a dynamic relocation. virtual bool usesOnlyLowPageBits(uint32_t Type) 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 bool needsThunk(uint32_t Type, 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(); @@ -92,6 +87,8 @@ 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; diff --git a/lld/ELF/Thunks.cpp b/lld/ELF/Thunks.cpp deleted file mode 100644 index 15d8c7e41e2..00000000000 --- a/lld/ELF/Thunks.cpp +++ /dev/null @@ -1,251 +0,0 @@ -//===- 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 diff --git a/lld/ELF/Thunks.h b/lld/ELF/Thunks.h deleted file mode 100644 index 676ff618d25..00000000000 --- a/lld/ELF/Thunks.h +++ /dev/null @@ -1,55 +0,0 @@ -//===- 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 = 0; - typename ELFT::uint getVA() const; - virtual void writeTo(uint8_t *Buf) const = 0; - 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 diff --git a/lld/test/ELF/arm-mov-relocs.s b/lld/test/ELF/arm-mov-relocs.s index 31ccba4ccea..6a254e8e09a 100644 --- a/lld/test/ELF/arm-mov-relocs.s +++ b/lld/test/ELF/arm-mov-relocs.s @@ -41,53 +41,16 @@ _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 diff --git a/lld/test/ELF/arm-thumb-interwork-thunk.s b/lld/test/ELF/arm-thumb-interwork-thunk.s deleted file mode 100644 index 6173df3c066..00000000000 --- a/lld/test/ELF/arm-thumb-interwork-thunk.s +++ /dev/null @@ -1,375 +0,0 @@ -// 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 |