From 3d2bbb13d0bd15d2dc5c7038447a398dbf40d2a9 Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Sat, 9 Jul 2016 22:52:30 +0000 Subject: [PATCH] Make ARM thunks consistent with MIPS in coding style. Although they are in the same .cpp file, the way they were written were slightly different, so they looked more different than they were. This patch makes their styles consistent. llvm-svn: 274996 --- lld/ELF/Thunks.cpp | 247 +++++++++++++++++++++++---------------------- lld/ELF/Thunks.h | 9 +- 2 files changed, 131 insertions(+), 125 deletions(-) diff --git a/lld/ELF/Thunks.cpp b/lld/ELF/Thunks.cpp index 26b54220ac0d..42c21ce3fda5 100644 --- a/lld/ELF/Thunks.cpp +++ b/lld/ELF/Thunks.cpp @@ -36,7 +36,130 @@ using namespace llvm::ELF; namespace lld { namespace elf { -template Thunk::~Thunk() {} +namespace { +// Specific ARM Thunk implementations. The naming convention is: +// Source State, TargetState, Target Requirement, ABS or PI, Range +template +class ARMToThumbV7ABSLongThunk final : public Thunk { +public: + ARMToThumbV7ABSLongThunk(const SymbolBody &Dest, + const InputSection &Owner) + : Thunk(Dest, Owner) {} + + uint32_t size() const override { return 12; } + void writeTo(uint8_t *Buf) const override; +}; + +template class ARMToThumbV7PILongThunk final : public Thunk { +public: + ARMToThumbV7PILongThunk(const SymbolBody &Dest, + const InputSection &Owner) + : Thunk(Dest, Owner) {} + + uint32_t size() const override { return 16; } + void writeTo(uint8_t *Buf) const override; +}; + +template +class ThumbToARMV7ABSLongThunk final : public Thunk { +public: + ThumbToARMV7ABSLongThunk(const SymbolBody &Dest, + const InputSection &Owner) + : Thunk(Dest, Owner) {} + + uint32_t size() const override { return 10; } + void writeTo(uint8_t *Buf) const override; +}; + +template class ThumbToARMV7PILongThunk final : public Thunk { +public: + ThumbToARMV7PILongThunk(const SymbolBody &Dest, + const InputSection &Owner) + : Thunk(Dest, Owner) {} + + uint32_t size() const override { return 12; } + void writeTo(uint8_t *Buf) const override; +}; + +// Mips thunk. +// Only the MIPS LA25 Thunk is supported, the implementation is delegated +// to the MipsTargetInfo class in Target.cpp +template class MipsThunk final : public Thunk { +public: + MipsThunk(const SymbolBody &Dest, const InputSection &Owner) + : Thunk(Dest, Owner) {} + + uint32_t size() const override { return 16; } + void writeTo(uint8_t *Buf) const override; +}; +} // anonymous namespace + +// ARM Target Thunks +template static uint64_t getARMThunkDestVA(const SymbolBody &S) { + return S.isInPlt() ? S.getPltVA() : S.getVA(); +} + +template +void ARMToThumbV7ABSLongThunk::writeTo(uint8_t *Buf) const { + const uint8_t Data[] = { + 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(this->Destination); + memcpy(Buf, Data, sizeof(Data)); + Target->relocateOne(Buf, R_ARM_MOVW_ABS_NC, S); + Target->relocateOne(Buf + 4, R_ARM_MOVT_ABS, S); +} + +template +void ThumbToARMV7ABSLongThunk::writeTo(uint8_t *Buf) const { + const uint8_t Data[] = { + 0x40, 0xf2, 0x00, 0x0c, // movw ip, :lower16:S + 0xc0, 0xf2, 0x00, 0x0c, // movt ip, :upper16:S + 0x60, 0x47, // bx ip + }; + uint64_t S = getARMThunkDestVA(this->Destination); + memcpy(Buf, Data, sizeof(Data)); + Target->relocateOne(Buf, R_ARM_THM_MOVW_ABS_NC, S); + Target->relocateOne(Buf + 4, R_ARM_THM_MOVT_ABS, S); +} + +template +void ARMToThumbV7PILongThunk::writeTo(uint8_t *Buf) const { + const uint8_t Data[] = { + 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(this->Destination); + uint64_t P = this->getVA(); + memcpy(Buf, Data, sizeof(Data)); + Target->relocateOne(Buf, R_ARM_MOVW_PREL_NC, S - P - 16); + Target->relocateOne(Buf + 4, R_ARM_MOVT_PREL, S - P - 12); +} + +template +void ThumbToARMV7PILongThunk::writeTo(uint8_t *Buf) const { + const uint8_t Data[] = { + 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(this->Destination); + uint64_t P = this->getVA(); + memcpy(Buf, Data, sizeof(Data)); + Target->relocateOne(Buf, R_ARM_THM_MOVW_PREL_NC, S - P - 12); + Target->relocateOne(Buf + 4, R_ARM_THM_MOVT_PREL, S - P - 8); +} + +template void MipsThunk::writeTo(uint8_t *Buf) const { + const SymbolBody &D = this->Destination; + uint64_t S = D.getVA(); + Target->writeThunk(Buf, S); +} template Thunk::Thunk(const SymbolBody &D, const InputSection &O) @@ -46,127 +169,7 @@ template typename ELFT::uint Thunk::getVA() const { return Owner.OutSec->getVA() + Owner.OutSecOff + Offset; } -// ARM Target Thunks -template static uint64_t getARMThunkDestVA(const SymbolBody &S) { - return S.isInPlt() ? S.getPltVA() : S.getVA(); -} - -// Specific ARM Thunk implementations. The naming convention is: -// Source State, TargetState, Target Requirement, ABS or PI, Range -namespace { -template -class ARMToThumbV7ABSLongThunk final : public Thunk { -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(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 &Owner) - : Thunk(Destination, Owner) {} -}; - -template class ARMToThumbV7PILongThunk final : public Thunk { -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(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 &Owner) - : Thunk(Destination, Owner) {} -}; - -template -class ThumbToARMV7ABSLongThunk final : public Thunk { -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(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 &Owner) - : Thunk(Destination, Owner) {} -}; - -template class ThumbToARMV7PILongThunk final : public Thunk { -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(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 &Owner) - : Thunk(Destination, Owner) {} -}; - -// Mips Thunks -// Only the MIPS LA25 Thunk is supported, the implementation is delegated -// to the MipsTargetInfo class in Target.cpp -template class MipsThunk : public Thunk { -public: - MipsThunk(const SymbolBody &Destination, const InputSection &Owner); - uint32_t size() const override; - void writeTo(uint8_t *Buf) const override; -}; - -template -MipsThunk::MipsThunk(const SymbolBody &Destination, - const InputSection &Owner) - : Thunk(Destination, Owner) {} - -template uint32_t MipsThunk::size() const { return 16; } - -template void MipsThunk::writeTo(uint8_t *Buf) const { - const SymbolBody &D = this->Destination; - uint64_t S = D.getVA(); - Target->writeThunk(Buf, S); -} -} +template Thunk::~Thunk() {} // Creates a thunk for Thumb-ARM interworking. template diff --git a/lld/ELF/Thunks.h b/lld/ELF/Thunks.h index 754bcadfea16..258f37f747d9 100644 --- a/lld/ELF/Thunks.h +++ b/lld/ELF/Thunks.h @@ -30,13 +30,16 @@ template class InputSectionBase; // is stored in a field of the Symbol Destination. // Thunks to be written to an InputSection are recorded by the InputSection. template class Thunk { + typedef typename ELFT::uint uintX_t; + 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 &Owner); virtual ~Thunk(); + virtual uint32_t size() const = 0; + virtual void writeTo(uint8_t *Buf) const = 0; + uintX_t getVA() const; + protected: const SymbolBody &Destination; const InputSection &Owner;