Index: lld/trunk/ELF/Target.cpp =================================================================== --- lld/trunk/ELF/Target.cpp +++ lld/trunk/ELF/Target.cpp @@ -102,7 +102,7 @@ void relaxTlsLdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; }; -class X86_64TargetInfo final : public TargetInfo { +template class X86_64TargetInfo final : public TargetInfo { public: X86_64TargetInfo(); RelExpr getRelExpr(uint32_t Type, const SymbolBody &S) const override; @@ -236,7 +236,9 @@ case EM_PPC64: return new PPC64TargetInfo(); case EM_X86_64: - return new X86_64TargetInfo(); + if (Config->EKind == ELF32LEKind) + return new X86_64TargetInfo(); + return new X86_64TargetInfo(); } fatal("unknown target machine"); } @@ -538,7 +540,7 @@ memcpy(Loc - 2, Inst, sizeof(Inst)); } -X86_64TargetInfo::X86_64TargetInfo() { +template X86_64TargetInfo::X86_64TargetInfo() { CopyRel = R_X86_64_COPY; GotRel = R_X86_64_GLOB_DAT; PltRel = R_X86_64_JUMP_SLOT; @@ -552,7 +554,9 @@ TlsGdRelaxSkip = 2; } -RelExpr X86_64TargetInfo::getRelExpr(uint32_t Type, const SymbolBody &S) const { +template +RelExpr X86_64TargetInfo::getRelExpr(uint32_t Type, + const SymbolBody &S) const { switch (Type) { default: return R_ABS; @@ -580,35 +584,40 @@ } } -void X86_64TargetInfo::writeGotPltHeader(uint8_t *Buf) const { +template +void X86_64TargetInfo::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::Dynamic->getVA()); + write64le(Buf, Out::Dynamic->getVA()); } -void X86_64TargetInfo::writeGotPlt(uint8_t *Buf, const SymbolBody &S) const { +template +void X86_64TargetInfo::writeGotPlt(uint8_t *Buf, + const SymbolBody &S) const { // See comments in X86TargetInfo::writeGotPlt. - write32le(Buf, S.getPltVA() + 6); + write32le(Buf, S.getPltVA() + 6); } -void X86_64TargetInfo::writePltHeader(uint8_t *Buf) const { +template +void X86_64TargetInfo::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::GotPlt->getVA(); - uint64_t Plt = Out::Plt->getVA(); + uint64_t Got = Out::GotPlt->getVA(); + uint64_t Plt = Out::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 +void X86_64TargetInfo::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 @@ -621,27 +630,32 @@ write32le(Buf + 12, -Index * PltEntrySize - PltHeaderSize - 16); } -uint32_t X86_64TargetInfo::getDynRel(uint32_t Type) const { +template +uint32_t X86_64TargetInfo::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 +bool X86_64TargetInfo::isTlsInitialExecRel(uint32_t Type) const { return Type == R_X86_64_GOTTPOFF; } -bool X86_64TargetInfo::isTlsGlobalDynamicRel(uint32_t Type) const { +template +bool X86_64TargetInfo::isTlsGlobalDynamicRel(uint32_t Type) const { return Type == R_X86_64_TLSGD; } -bool X86_64TargetInfo::isTlsLocalDynamicRel(uint32_t Type) const { +template +bool X86_64TargetInfo::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 +void X86_64TargetInfo::relaxTlsGdToLe(uint8_t *Loc, uint32_t Type, + uint64_t Val) const { // Convert // .byte 0x66 // leaq x@tlsgd(%rip), %rdi @@ -661,8 +675,9 @@ relocateOne(Loc + 8, R_X86_64_TPOFF32, Val + 4); } -void X86_64TargetInfo::relaxTlsGdToIe(uint8_t *Loc, uint32_t Type, - uint64_t Val) const { +template +void X86_64TargetInfo::relaxTlsGdToIe(uint8_t *Loc, uint32_t Type, + uint64_t Val) const { // Convert // .byte 0x66 // leaq x@tlsgd(%rip), %rdi @@ -684,8 +699,9 @@ // 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 +void X86_64TargetInfo::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 @@ relocateOne(Loc, R_X86_64_TPOFF32, Val + 4); } -void X86_64TargetInfo::relaxTlsLdToLe(uint8_t *Loc, uint32_t Type, - uint64_t Val) const { +template +void X86_64TargetInfo::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 @@ memcpy(Loc - 3, Inst, sizeof(Inst)); } -void X86_64TargetInfo::relocateOne(uint8_t *Loc, uint32_t Type, - uint64_t Val) const { +template +void X86_64TargetInfo::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 @@ } } -RelExpr X86_64TargetInfo::adjustRelaxExpr(uint32_t Type, const uint8_t *Data, - RelExpr RelExpr) const { +template +RelExpr X86_64TargetInfo::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 @@ // "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 +void X86_64TargetInfo::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 @@ relocateOne(Loc, R_X86_64_PC32, Val); } -void X86_64TargetInfo::relaxGot(uint8_t *Loc, uint64_t Val) const { +template +void X86_64TargetInfo::relaxGot(uint8_t *Loc, uint64_t Val) const { const uint8_t Op = Loc[-2]; const uint8_t ModRm = Loc[-1];