diff options
Diffstat (limited to 'ELF/Target.cpp')
| -rw-r--r-- | ELF/Target.cpp | 178 |
1 files changed, 153 insertions, 25 deletions
diff --git a/ELF/Target.cpp b/ELF/Target.cpp index 8d54c93570fa..6d42dbe86e54 100644 --- a/ELF/Target.cpp +++ b/ELF/Target.cpp @@ -122,7 +122,6 @@ private: class X86_64TargetInfo final : public TargetInfo { public: X86_64TargetInfo(); - unsigned getPltRefReloc(unsigned Type) const override; bool isTlsDynReloc(unsigned Type, const SymbolBody &S) const override; void writeGotPltHeaderEntries(uint8_t *Buf) const override; void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override; @@ -139,7 +138,7 @@ public: uint8_t *PairedLoc = nullptr) const override; bool isRelRelative(uint32_t Type) const override; bool isTlsOptimized(unsigned Type, const SymbolBody *S) const override; - bool isSizeDynReloc(uint32_t Type, const SymbolBody &S) const override; + bool isSizeReloc(uint32_t Type) const override; unsigned relocateTlsOptimize(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P, uint64_t SA, const SymbolBody &S) const override; @@ -155,6 +154,23 @@ private: uint64_t SA) const; }; +class PPCTargetInfo final : public TargetInfo { +public: + PPCTargetInfo(); + void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override; + void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr, + uint64_t PltEntryAddr) const override; + void writePltEntry(uint8_t *Buf, uint64_t GotAddr, uint64_t GotEntryAddr, + uint64_t PltEntryAddr, int32_t Index, + unsigned RelOff) const override; + bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override; + bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override; + void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P, + uint64_t SA, uint64_t ZA = 0, + uint8_t *PairedLoc = nullptr) const override; + bool isRelRelative(uint32_t Type) const override; +}; + class PPC64TargetInfo final : public TargetInfo { public: PPC64TargetInfo(); @@ -176,13 +192,14 @@ class AArch64TargetInfo final : public TargetInfo { public: AArch64TargetInfo(); unsigned getDynReloc(unsigned Type) const override; - unsigned getPltRefReloc(unsigned Type) const override; void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override; void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr) const override; void writePltEntry(uint8_t *Buf, uint64_t GotAddr, uint64_t GotEntryAddr, uint64_t PltEntryAddr, int32_t Index, unsigned RelOff) const override; + unsigned getTlsGotReloc(unsigned Type = -1) const override; + bool isTlsDynReloc(unsigned Type, const SymbolBody &S) const override; bool needsCopyRel(uint32_t Type, const SymbolBody &S) const override; bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override; bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override; @@ -191,6 +208,22 @@ public: uint8_t *PairedLoc = nullptr) const override; }; +class AMDGPUTargetInfo final : public TargetInfo { +public: + AMDGPUTargetInfo(); + void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override; + void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr, + uint64_t PltEntryAddr) const override; + void writePltEntry(uint8_t *Buf, uint64_t GotAddr, uint64_t GotEntryAddr, + uint64_t PltEntryAddr, int32_t Index, + unsigned RelOff) const override; + bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override; + bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override; + void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P, + uint64_t SA, uint64_t ZA = 0, + uint8_t *PairedLoc = nullptr) const override; +}; + template <class ELFT> class MipsTargetInfo final : public TargetInfo { public: MipsTargetInfo(); @@ -216,6 +249,8 @@ TargetInfo *createTarget() { return new X86TargetInfo(); case EM_AARCH64: return new AArch64TargetInfo(); + case EM_AMDGPU: + return new AMDGPUTargetInfo(); case EM_MIPS: switch (Config->EKind) { case ELF32LEKind: @@ -225,6 +260,8 @@ TargetInfo *createTarget() { default: error("Unsupported MIPS target"); } + case EM_PPC: + return new PPCTargetInfo(); case EM_PPC64: return new PPC64TargetInfo(); case EM_X86_64: @@ -247,13 +284,9 @@ bool TargetInfo::needsCopyRel(uint32_t Type, const SymbolBody &S) const { bool TargetInfo::isGotRelative(uint32_t Type) const { return false; } -unsigned TargetInfo::getPltRefReloc(unsigned Type) const { return PCRelReloc; } - bool TargetInfo::isRelRelative(uint32_t Type) const { return true; } -bool TargetInfo::isSizeDynReloc(uint32_t Type, const SymbolBody &S) const { - return false; -} +bool TargetInfo::isSizeReloc(uint32_t Type) const { return false; } unsigned TargetInfo::relocateTlsOptimize(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P, uint64_t SA, @@ -639,12 +672,6 @@ bool X86_64TargetInfo::isTlsDynReloc(unsigned Type, const SymbolBody &S) const { return Type == R_X86_64_GOTTPOFF || Type == R_X86_64_TLSGD; } -unsigned X86_64TargetInfo::getPltRefReloc(unsigned Type) const { - if (Type == R_X86_64_PLT32) - return R_X86_64_PC32; - return Type; -} - bool X86_64TargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const { if (needsCopyRel(Type, S)) return false; @@ -698,16 +725,12 @@ bool X86_64TargetInfo::isRelRelative(uint32_t Type) const { case R_X86_64_PC32: case R_X86_64_PC64: case R_X86_64_PLT32: - case R_X86_64_SIZE32: - case R_X86_64_SIZE64: return true; } } -bool X86_64TargetInfo::isSizeDynReloc(uint32_t Type, - const SymbolBody &S) const { - return (Type == R_X86_64_SIZE32 || Type == R_X86_64_SIZE64) && - canBePreempted(&S, false); +bool X86_64TargetInfo::isSizeReloc(uint32_t Type) const { + return Type == R_X86_64_SIZE32 || Type == R_X86_64_SIZE64; } bool X86_64TargetInfo::isTlsOptimized(unsigned Type, @@ -909,6 +932,37 @@ static uint16_t applyPPCHighera(uint64_t V) { return (V + 0x8000) >> 32; } static uint16_t applyPPCHighest(uint64_t V) { return V >> 48; } static uint16_t applyPPCHighesta(uint64_t V) { return (V + 0x8000) >> 48; } +PPCTargetInfo::PPCTargetInfo() {} +void PPCTargetInfo::writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const {} +void PPCTargetInfo::writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr, + uint64_t PltEntryAddr) const {} +void PPCTargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotAddr, + uint64_t GotEntryAddr, + uint64_t PltEntryAddr, int32_t Index, + unsigned RelOff) const {} +bool PPCTargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const { + return false; +} +bool PPCTargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const { + return false; +} +bool PPCTargetInfo::isRelRelative(uint32_t Type) const { return false; } + +void PPCTargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, + uint64_t P, uint64_t SA, uint64_t ZA, + uint8_t *PairedLoc) const { + switch (Type) { + case R_PPC_ADDR16_HA: + write16be(Loc, applyPPCHa(SA)); + break; + case R_PPC_ADDR16_LO: + write16be(Loc, applyPPCLo(SA)); + break; + default: + error("unrecognized reloc " + Twine(Type)); + } +} + PPC64TargetInfo::PPC64TargetInfo() { PCRelReloc = R_PPC64_REL24; GotReloc = R_PPC64_GLOB_DAT; @@ -1124,8 +1178,10 @@ void PPC64TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, AArch64TargetInfo::AArch64TargetInfo() { CopyReloc = R_AARCH64_COPY; + IRelativeReloc = R_AARCH64_IRELATIVE; GotReloc = R_AARCH64_GLOB_DAT; PltReloc = R_AARCH64_JUMP_SLOT; + TlsGotReloc = R_AARCH64_TLS_TPREL64; LazyRelocations = true; PltEntrySize = 16; PltZeroEntrySize = 32; @@ -1139,8 +1195,6 @@ unsigned AArch64TargetInfo::getDynReloc(unsigned Type) const { "recompile with -fPIC."); } -unsigned AArch64TargetInfo::getPltRefReloc(unsigned Type) const { return Type; } - void AArch64TargetInfo::writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const { write64le(Buf, Out<ELF64LE>::Plt->getVA()); } @@ -1187,6 +1241,19 @@ void AArch64TargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotAddr, GotEntryAddr); } +unsigned AArch64TargetInfo::getTlsGotReloc(unsigned Type) const { + if (Type == R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 || + Type == R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC) + return Type; + return TlsGotReloc; +} + +bool AArch64TargetInfo::isTlsDynReloc(unsigned Type, + const SymbolBody &S) const { + return Type == R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 || + Type == R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC; +} + bool AArch64TargetInfo::needsCopyRel(uint32_t Type, const SymbolBody &S) const { if (Config->Shared) return false; @@ -1210,17 +1277,28 @@ bool AArch64TargetInfo::needsCopyRel(uint32_t Type, const SymbolBody &S) const { bool AArch64TargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const { - return Type == R_AARCH64_ADR_GOT_PAGE || Type == R_AARCH64_LD64_GOT_LO12_NC || - relocNeedsPlt(Type, S); + switch (Type) { + case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: + case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: + case R_AARCH64_ADR_GOT_PAGE: + case R_AARCH64_LD64_GOT_LO12_NC: + return true; + default: + return relocNeedsPlt(Type, S); + } } bool AArch64TargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const { + if (isGnuIFunc<ELF64LE>(S)) + return true; switch (Type) { default: return false; case R_AARCH64_CALL26: + case R_AARCH64_CONDBR19: case R_AARCH64_JUMP26: + case R_AARCH64_TSTBR14: return canBePreempted(&S, true); } } @@ -1273,7 +1351,8 @@ void AArch64TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, updateAArch64Adr(Loc, X & 0x1FFFFF); break; } - case R_AARCH64_ADR_PREL_PG_HI21: { + case R_AARCH64_ADR_PREL_PG_HI21: + case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: { uint64_t X = getAArch64Page(SA) - getAArch64Page(P); checkInt<33>(X, Type); updateAArch64Adr(Loc, (X >> 12) & 0x1FFFFF); // X[32:12] @@ -1286,7 +1365,14 @@ void AArch64TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, or32le(Loc, (X & 0x0FFFFFFC) >> 2); break; } + case R_AARCH64_CONDBR19: { + uint64_t X = SA - P; + checkInt<21>(X, Type); + or32le(Loc, (X & 0x1FFFFC) << 3); + break; + } case R_AARCH64_LD64_GOT_LO12_NC: + case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: checkAlignment<8>(SA, Type); or32le(Loc, (SA & 0xFF8) << 7); break; @@ -1310,11 +1396,53 @@ void AArch64TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, case R_AARCH64_PREL64: write64le(Loc, SA - P); break; + case R_AARCH64_TSTBR14: { + uint64_t X = SA - P; + checkInt<16>(X, Type); + or32le(Loc, (X & 0xFFFC) << 3); + break; + } default: error("unrecognized reloc " + Twine(Type)); } } +AMDGPUTargetInfo::AMDGPUTargetInfo() {} + +void AMDGPUTargetInfo::writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const { + llvm_unreachable("not implemented"); +} + +void AMDGPUTargetInfo::writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr, + uint64_t PltEntryAddr) const { + llvm_unreachable("not implemented"); +} + +void AMDGPUTargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotAddr, + uint64_t GotEntryAddr, + uint64_t PltEntryAddr, int32_t Index, + unsigned RelOff) const { + llvm_unreachable("not implemented"); +} + +bool AMDGPUTargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const { + return false; +} + +bool AMDGPUTargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const { + return false; +} + +// Implementing relocations for AMDGPU is low priority since most +// programs don't use relocations now. Thus, this function is not +// actually called (relocateOne is called for each relocation). +// That's why the AMDGPU port works without implementing this function. +void AMDGPUTargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, + uint64_t P, uint64_t SA, uint64_t ZA, + uint8_t *PairedLoc) const { + llvm_unreachable("not implemented"); +} + template <class ELFT> MipsTargetInfo<ELFT>::MipsTargetInfo() { PageSize = 65536; GotHeaderEntriesNum = 2; |
