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>();
-}
-
+namespace {
// 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,
+ ARMToThumbV7ABSLongThunk(const SymbolBody &Dest,
const InputSection<ELFT> &Owner)
- : Thunk<ELFT>(Destination, Owner) {}
+ : Thunk<ELFT>(Dest, Owner) {}
+
+ uint32_t size() const override { return 12; }
+ void writeTo(uint8_t *Buf) const override;
};
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,
+ ARMToThumbV7PILongThunk(const SymbolBody &Dest,
const InputSection<ELFT> &Owner)
- : Thunk<ELFT>(Destination, Owner) {}
+ : Thunk<ELFT>(Dest, Owner) {}
+
+ uint32_t size() const override { return 16; }
+ void writeTo(uint8_t *Buf) const override;
};
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,
+ ThumbToARMV7ABSLongThunk(const SymbolBody &Dest,
const InputSection<ELFT> &Owner)
- : Thunk<ELFT>(Destination, Owner) {}
+ : Thunk<ELFT>(Dest, Owner) {}
+
+ uint32_t size() const override { return 10; }
+ void writeTo(uint8_t *Buf) const override;
};
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,
+ ThumbToARMV7PILongThunk(const SymbolBody &Dest,
const InputSection<ELFT> &Owner)
- : Thunk<ELFT>(Destination, Owner) {}
+ : Thunk<ELFT>(Dest, Owner) {}
+
+ uint32_t size() const override { return 12; }
+ void writeTo(uint8_t *Buf) const override;
};
-// Mips Thunks
+// Mips thunk.
// 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> {
+template <class ELFT> class MipsThunk final : public Thunk<ELFT> {
public:
- MipsThunk(const SymbolBody &Destination, const InputSection<ELFT> &Owner);
- uint32_t size() const override;
+ MipsThunk(const SymbolBody &Dest, const InputSection<ELFT> &Owner)
+ : Thunk<ELFT>(Dest, Owner) {}
+
+ uint32_t size() const override { return 16; }
void writeTo(uint8_t *Buf) const override;
};
+} // anonymous namespace
+
+// ARM Target Thunks
+template <class ELFT> static uint64_t getARMThunkDestVA(const SymbolBody &S) {
+ return S.isInPlt() ? S.getPltVA<ELFT>() : S.getVA<ELFT>();
+}
template <class ELFT>
-MipsThunk<ELFT>::MipsThunk(const SymbolBody &Destination,
- const InputSection<ELFT> &Owner)
- : Thunk<ELFT>(Destination, Owner) {}
+void ARMToThumbV7ABSLongThunk<ELFT>::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<ELFT>(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 <class ELFT> uint32_t MipsThunk<ELFT>::size() const { return 16; }
+template <class ELFT>
+void ThumbToARMV7ABSLongThunk<ELFT>::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<ELFT>(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 <class ELFT>
+void ARMToThumbV7PILongThunk<ELFT>::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<ELFT>(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 <class ELFT>
+void ThumbToARMV7PILongThunk<ELFT>::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<ELFT>(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 <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>
+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;
}
+template <class ELFT> Thunk<ELFT>::~Thunk() {}
+
// Creates a thunk for Thumb-ARM interworking.
template <class ELFT>
static Thunk<ELFT> *createThunkArm(uint32_t Reloc, SymbolBody &S,