[lld] r275235 - Add ILP32 support to X86_64TargetInfo.
Rui Ueyama via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 12 16:28:31 PDT 2016
Author: ruiu
Date: Tue Jul 12 18:28:31 2016
New Revision: 275235
URL: http://llvm.org/viewvc/llvm-project?rev=275235&view=rev
Log:
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
Modified:
lld/trunk/ELF/Target.cpp
Modified: lld/trunk/ELF/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.cpp?rev=275235&r1=275234&r2=275235&view=diff
==============================================================================
--- lld/trunk/ELF/Target.cpp (original)
+++ lld/trunk/ELF/Target.cpp Tue Jul 12 18:28:31 2016
@@ -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
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(uin
}
}
-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
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 at tlsgd(%rip), %rdi
@@ -661,8 +675,9 @@ void X86_64TargetInfo::relaxTlsGdToLe(ui
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 at tlsgd(%rip), %rdi
@@ -684,8 +699,9 @@ void X86_64TargetInfo::relaxTlsGdToIe(ui
// 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(ui
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 at tlsld(%rip), %rdi
// callq __tls_get_addr at PLT
@@ -753,8 +770,9 @@ void X86_64TargetInfo::relaxTlsLdToLe(ui
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
}
}
-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::adjustRelaxExp
// "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 at GOTPCREL(%rip)" to "test $foo, %reg".
if (Op == 0x85) {
@@ -879,7 +900,8 @@ void X86_64TargetInfo::relaxGotNoPic(uin
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];
More information about the llvm-commits
mailing list