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
This commit is contained in:
Rui Ueyama 2016-07-09 22:52:30 +00:00
parent c4890705ef
commit 3d2bbb13d0
2 changed files with 131 additions and 125 deletions

View File

@ -36,7 +36,130 @@ using namespace llvm::ELF;
namespace lld { namespace lld {
namespace elf { namespace elf {
template <class ELFT> Thunk<ELFT>::~Thunk() {} namespace {
// Specific ARM Thunk implementations. The naming convention is:
// Source State, TargetState, Target Requirement, ABS or PI, Range
template <class ELFT>
class ARMToThumbV7ABSLongThunk final : public Thunk<ELFT> {
public:
ARMToThumbV7ABSLongThunk(const SymbolBody &Dest,
const InputSection<ELFT> &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:
ARMToThumbV7PILongThunk(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;
};
template <class ELFT>
class ThumbToARMV7ABSLongThunk final : public Thunk<ELFT> {
public:
ThumbToARMV7ABSLongThunk(const SymbolBody &Dest,
const InputSection<ELFT> &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:
ThumbToARMV7PILongThunk(const SymbolBody &Dest,
const InputSection<ELFT> &Owner)
: Thunk<ELFT>(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 ELFT> class MipsThunk final : public Thunk<ELFT> {
public:
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>
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>
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> template <class ELFT>
Thunk<ELFT>::Thunk(const SymbolBody &D, const InputSection<ELFT> &O) Thunk<ELFT>::Thunk(const SymbolBody &D, const InputSection<ELFT> &O)
@ -46,127 +169,7 @@ template <class ELFT> typename ELFT::uint Thunk<ELFT>::getVA() const {
return Owner.OutSec->getVA() + Owner.OutSecOff + Offset; return Owner.OutSec->getVA() + Owner.OutSecOff + Offset;
} }
// ARM Target Thunks template <class ELFT> Thunk<ELFT>::~Thunk() {}
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);
}
}
// Creates a thunk for Thumb-ARM interworking. // Creates a thunk for Thumb-ARM interworking.
template <class ELFT> template <class ELFT>

View File

@ -30,13 +30,16 @@ template <class ELFT> class InputSectionBase;
// is stored in a field of the Symbol Destination. // is stored in a field of the Symbol Destination.
// Thunks to be written to an InputSection are recorded by the InputSection. // Thunks to be written to an InputSection are recorded by the InputSection.
template <class ELFT> class Thunk { template <class ELFT> class Thunk {
typedef typename ELFT::uint uintX_t;
public: 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); Thunk(const SymbolBody &Destination, const InputSection<ELFT> &Owner);
virtual ~Thunk(); virtual ~Thunk();
virtual uint32_t size() const = 0;
virtual void writeTo(uint8_t *Buf) const = 0;
uintX_t getVA() const;
protected: protected:
const SymbolBody &Destination; const SymbolBody &Destination;
const InputSection<ELFT> &Owner; const InputSection<ELFT> &Owner;