diff options
author | Rui Ueyama <ruiu@google.com> | 2016-07-12 23:28:31 +0000 |
---|---|---|
committer | Rui Ueyama <ruiu@google.com> | 2016-07-12 23:28:31 +0000 |
commit | 46626e1f049f74c445bbf0179f251f6934993630 (patch) | |
tree | 048bf5e9d7fbca9ec88815cc9de859e7b9fc5b98 | |
parent | b933df1835ffb47bcededacfd568f63bc191acb8 (diff) | |
download | bcm5719-llvm-46626e1f049f74c445bbf0179f251f6934993630.tar.gz bcm5719-llvm-46626e1f049f74c445bbf0179f251f6934993630.zip |
Add ILP32 support to X86_64TargetInfo.
Patch by H.J. Lu.
As x86-64 psABI supports both LP64 and ILP32, this patch adds <ELFT>
template to X86_64TargetInfo.
Differential Revision: http://reviews.llvm.org/D22287
llvm-svn: 275235
-rw-r--r-- | lld/ELF/Target.cpp | 88 |
1 files changed, 55 insertions, 33 deletions
diff --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp index e822904ba8f..c27af428032 100644 --- a/lld/ELF/Target.cpp +++ b/lld/ELF/Target.cpp @@ -102,7 +102,7 @@ public: void relaxTlsLdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; }; -class X86_64TargetInfo final : public TargetInfo { +template <class ELFT> class X86_64TargetInfo final : public TargetInfo { public: X86_64TargetInfo(); RelExpr getRelExpr(uint32_t Type, const SymbolBody &S) const override; @@ -236,7 +236,9 @@ TargetInfo *createTarget() { case EM_PPC64: return new PPC64TargetInfo(); case EM_X86_64: - return new X86_64TargetInfo(); + if (Config->EKind == ELF32LEKind) + return new X86_64TargetInfo<ELF32LE>(); + return new X86_64TargetInfo<ELF64LE>(); } fatal("unknown target machine"); } @@ -538,7 +540,7 @@ void X86TargetInfo::relaxTlsLdToLe(uint8_t *Loc, uint32_t Type, memcpy(Loc - 2, Inst, sizeof(Inst)); } -X86_64TargetInfo::X86_64TargetInfo() { +template <class ELFT> X86_64TargetInfo<ELFT>::X86_64TargetInfo() { CopyRel = R_X86_64_COPY; GotRel = R_X86_64_GLOB_DAT; PltRel = R_X86_64_JUMP_SLOT; @@ -552,7 +554,9 @@ X86_64TargetInfo::X86_64TargetInfo() { TlsGdRelaxSkip = 2; } -RelExpr X86_64TargetInfo::getRelExpr(uint32_t Type, const SymbolBody &S) const { +template <class ELFT> +RelExpr X86_64TargetInfo<ELFT>::getRelExpr(uint32_t Type, + const SymbolBody &S) const { switch (Type) { default: return R_ABS; @@ -580,35 +584,40 @@ RelExpr X86_64TargetInfo::getRelExpr(uint32_t Type, const SymbolBody &S) const { } } -void X86_64TargetInfo::writeGotPltHeader(uint8_t *Buf) const { +template <class ELFT> +void X86_64TargetInfo<ELFT>::writeGotPltHeader(uint8_t *Buf) const { // The first entry holds the value of _DYNAMIC. It is not clear why that is // required, but it is documented in the psabi and the glibc dynamic linker // seems to use it (note that this is relevant for linking ld.so, not any // other program). - write64le(Buf, Out<ELF64LE>::Dynamic->getVA()); + write64le(Buf, Out<ELFT>::Dynamic->getVA()); } -void X86_64TargetInfo::writeGotPlt(uint8_t *Buf, const SymbolBody &S) const { +template <class ELFT> +void X86_64TargetInfo<ELFT>::writeGotPlt(uint8_t *Buf, + const SymbolBody &S) const { // See comments in X86TargetInfo::writeGotPlt. - write32le(Buf, S.getPltVA<ELF64LE>() + 6); + write32le(Buf, S.getPltVA<ELFT>() + 6); } -void X86_64TargetInfo::writePltHeader(uint8_t *Buf) const { +template <class ELFT> +void X86_64TargetInfo<ELFT>::writePltHeader(uint8_t *Buf) const { const uint8_t PltData[] = { 0xff, 0x35, 0x00, 0x00, 0x00, 0x00, // pushq GOT+8(%rip) 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp *GOT+16(%rip) 0x0f, 0x1f, 0x40, 0x00 // nopl 0x0(rax) }; memcpy(Buf, PltData, sizeof(PltData)); - uint64_t Got = Out<ELF64LE>::GotPlt->getVA(); - uint64_t Plt = Out<ELF64LE>::Plt->getVA(); + uint64_t Got = Out<ELFT>::GotPlt->getVA(); + uint64_t Plt = Out<ELFT>::Plt->getVA(); write32le(Buf + 2, Got - Plt + 2); // GOT+8 write32le(Buf + 8, Got - Plt + 4); // GOT+16 } -void X86_64TargetInfo::writePlt(uint8_t *Buf, uint64_t GotEntryAddr, - uint64_t PltEntryAddr, int32_t Index, - unsigned RelOff) const { +template <class ELFT> +void X86_64TargetInfo<ELFT>::writePlt(uint8_t *Buf, uint64_t GotEntryAddr, + uint64_t PltEntryAddr, int32_t Index, + unsigned RelOff) const { const uint8_t Inst[] = { 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmpq *got(%rip) 0x68, 0x00, 0x00, 0x00, 0x00, // pushq <relocation index> @@ -621,27 +630,32 @@ void X86_64TargetInfo::writePlt(uint8_t *Buf, uint64_t GotEntryAddr, write32le(Buf + 12, -Index * PltEntrySize - PltHeaderSize - 16); } -uint32_t X86_64TargetInfo::getDynRel(uint32_t Type) const { +template <class ELFT> +uint32_t X86_64TargetInfo<ELFT>::getDynRel(uint32_t Type) const { if (Type == R_X86_64_PC32 || Type == R_X86_64_32) errorDynRel(Type); return Type; } -bool X86_64TargetInfo::isTlsInitialExecRel(uint32_t Type) const { +template <class ELFT> +bool X86_64TargetInfo<ELFT>::isTlsInitialExecRel(uint32_t Type) const { return Type == R_X86_64_GOTTPOFF; } -bool X86_64TargetInfo::isTlsGlobalDynamicRel(uint32_t Type) const { +template <class ELFT> +bool X86_64TargetInfo<ELFT>::isTlsGlobalDynamicRel(uint32_t Type) const { return Type == R_X86_64_TLSGD; } -bool X86_64TargetInfo::isTlsLocalDynamicRel(uint32_t Type) const { +template <class ELFT> +bool X86_64TargetInfo<ELFT>::isTlsLocalDynamicRel(uint32_t Type) const { return Type == R_X86_64_DTPOFF32 || Type == R_X86_64_DTPOFF64 || Type == R_X86_64_TLSLD; } -void X86_64TargetInfo::relaxTlsGdToLe(uint8_t *Loc, uint32_t Type, - uint64_t Val) const { +template <class ELFT> +void X86_64TargetInfo<ELFT>::relaxTlsGdToLe(uint8_t *Loc, uint32_t Type, + uint64_t Val) const { // Convert // .byte 0x66 // leaq x@tlsgd(%rip), %rdi @@ -661,8 +675,9 @@ void X86_64TargetInfo::relaxTlsGdToLe(uint8_t *Loc, uint32_t Type, relocateOne(Loc + 8, R_X86_64_TPOFF32, Val + 4); } -void X86_64TargetInfo::relaxTlsGdToIe(uint8_t *Loc, uint32_t Type, - uint64_t Val) const { +template <class ELFT> +void X86_64TargetInfo<ELFT>::relaxTlsGdToIe(uint8_t *Loc, uint32_t Type, + uint64_t Val) const { // Convert // .byte 0x66 // leaq x@tlsgd(%rip), %rdi @@ -684,8 +699,9 @@ void X86_64TargetInfo::relaxTlsGdToIe(uint8_t *Loc, uint32_t Type, // In some conditions, R_X86_64_GOTTPOFF relocation can be optimized to // R_X86_64_TPOFF32 so that it does not use GOT. -void X86_64TargetInfo::relaxTlsIeToLe(uint8_t *Loc, uint32_t Type, - uint64_t Val) const { +template <class ELFT> +void X86_64TargetInfo<ELFT>::relaxTlsIeToLe(uint8_t *Loc, uint32_t Type, + uint64_t Val) const { uint8_t *Inst = Loc - 3; uint8_t Reg = Loc[-1] >> 3; uint8_t *RegSlot = Loc - 1; @@ -725,8 +741,9 @@ void X86_64TargetInfo::relaxTlsIeToLe(uint8_t *Loc, uint32_t Type, relocateOne(Loc, R_X86_64_TPOFF32, Val + 4); } -void X86_64TargetInfo::relaxTlsLdToLe(uint8_t *Loc, uint32_t Type, - uint64_t Val) const { +template <class ELFT> +void X86_64TargetInfo<ELFT>::relaxTlsLdToLe(uint8_t *Loc, uint32_t Type, + uint64_t Val) const { // Convert // leaq bar@tlsld(%rip), %rdi // callq __tls_get_addr@PLT @@ -753,8 +770,9 @@ void X86_64TargetInfo::relaxTlsLdToLe(uint8_t *Loc, uint32_t Type, memcpy(Loc - 3, Inst, sizeof(Inst)); } -void X86_64TargetInfo::relocateOne(uint8_t *Loc, uint32_t Type, - uint64_t Val) const { +template <class ELFT> +void X86_64TargetInfo<ELFT>::relocateOne(uint8_t *Loc, uint32_t Type, + uint64_t Val) const { switch (Type) { case R_X86_64_32: checkUInt<32>(Val, Type); @@ -787,8 +805,10 @@ void X86_64TargetInfo::relocateOne(uint8_t *Loc, uint32_t Type, } } -RelExpr X86_64TargetInfo::adjustRelaxExpr(uint32_t Type, const uint8_t *Data, - RelExpr RelExpr) const { +template <class ELFT> +RelExpr X86_64TargetInfo<ELFT>::adjustRelaxExpr(uint32_t Type, + const uint8_t *Data, + RelExpr RelExpr) const { if (Type != R_X86_64_GOTPCRELX && Type != R_X86_64_REX_GOTPCRELX) return RelExpr; const uint8_t Op = Data[-2]; @@ -816,8 +836,9 @@ RelExpr X86_64TargetInfo::adjustRelaxExpr(uint32_t Type, const uint8_t *Data, // "Intel 64 and IA-32 Architectures Software Developer's Manual V2" // (http://www.intel.com/content/dam/www/public/us/en/documents/manuals/ // 64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf) -void X86_64TargetInfo::relaxGotNoPic(uint8_t *Loc, uint64_t Val, uint8_t Op, - uint8_t ModRm) const { +template <class ELFT> +void X86_64TargetInfo<ELFT>::relaxGotNoPic(uint8_t *Loc, uint64_t Val, + uint8_t Op, uint8_t ModRm) const { const uint8_t Rex = Loc[-3]; // Convert "test %reg, foo@GOTPCREL(%rip)" to "test $foo, %reg". if (Op == 0x85) { @@ -879,7 +900,8 @@ void X86_64TargetInfo::relaxGotNoPic(uint8_t *Loc, uint64_t Val, uint8_t Op, relocateOne(Loc, R_X86_64_PC32, Val); } -void X86_64TargetInfo::relaxGot(uint8_t *Loc, uint64_t Val) const { +template <class ELFT> +void X86_64TargetInfo<ELFT>::relaxGot(uint8_t *Loc, uint64_t Val) const { const uint8_t Op = Loc[-2]; const uint8_t ModRm = Loc[-1]; |