Index: ELF/InputSection.cpp =================================================================== --- ELF/InputSection.cpp +++ ELF/InputSection.cpp @@ -155,19 +155,19 @@ uintX_t AddrLoc = OutSec->getVA() + Offset; auto NextRelocs = llvm::make_range(&RI, Rels.end()); + const Elf_Shdr *SymTab = File->getSymbolTable(); + SymbolBody *Body = nullptr; + if (SymIndex >= SymTab->sh_info) + Body = File->getSymbolBody(SymIndex)->repl(); + if (Target->isTlsLocalDynamicRel(Type) && !Target->canRelaxTls(Type, nullptr)) { - Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc, + Target->relocateOne(File, Body, BufLoc, BufEnd, Type, AddrLoc, Out::Got->getLocalTlsIndexVA() + getAddend(RI)); continue; } - const Elf_Shdr *SymTab = File->getSymbolTable(); - SymbolBody *Body = nullptr; - if (SymIndex >= SymTab->sh_info) - Body = File->getSymbolBody(SymIndex)->repl(); - if (Target->canRelaxTls(Type, Body)) { uintX_t SymVA; if (!Body) @@ -188,26 +188,14 @@ uintX_t A = getAddend(RI); if (!Body) { uintX_t SymVA = getLocalRelTarget(*File, RI, A); - if (Config->EMachine == EM_MIPS) { - if (Type == R_MIPS_GPREL16 || Type == R_MIPS_GPREL32) - // We need to adjust SymVA value in case of R_MIPS_GPREL16/32 - // relocations because they use the following expression to calculate - // the relocation's result for local symbol: S + A + GP0 - G. - SymVA += File->getMipsGp0(); - else if (Type == R_MIPS_GOT16) - // R_MIPS_GOT16 relocation against local symbol requires index of - // a local GOT entry which contains page address corresponds - // to the symbol address. - SymVA = Out::Got->getMipsLocalPageAddr(SymVA); - } - Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc, SymVA, 0, + Target->relocateOne(File, Body, BufLoc, BufEnd, Type, AddrLoc, SymVA, 0, findMipsPairedReloc(Buf, SymIndex, Type, NextRelocs)); continue; } if (Target->isTlsGlobalDynamicRel(Type) && !Target->canRelaxTls(Type, Body)) { - Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc, + Target->relocateOne(File, Body, BufLoc, BufEnd, Type, AddrLoc, Out::Got->getGlobalDynAddr(*Body) + getAddend(RI)); continue; @@ -237,14 +225,10 @@ // If that's the case, we leave the field alone rather than filling it // with a possibly incorrect value. continue; - } else if (Config->EMachine == EM_MIPS) { - if (Type == R_MIPS_HI16 && Body == Config->MipsGpDisp) - SymVA = getMipsGpAddr() - AddrLoc; - else if (Type == R_MIPS_LO16 && Body == Config->MipsGpDisp) - SymVA = getMipsGpAddr() - AddrLoc + 4; } uintX_t Size = getSymSize(*Body); - Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc, SymVA + A, Size + A, + Target->relocateOne(File, Body, BufLoc, BufEnd, Type, AddrLoc, SymVA + A, + Size + A, findMipsPairedReloc(Buf, SymIndex, Type, NextRelocs)); } } Index: ELF/Target.h =================================================================== --- ELF/Target.h +++ ELF/Target.h @@ -17,6 +17,7 @@ namespace lld { namespace elf2 { +class InputFile; class SymbolBody; class TargetInfo { @@ -56,7 +57,8 @@ virtual bool needsDynRelative(unsigned Type) const { return false; } virtual bool needsGot(uint32_t Type, const SymbolBody &S) const; virtual bool needsPlt(uint32_t Type, const SymbolBody &S) const; - virtual void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, + virtual void relocateOne(const InputFile *File, const SymbolBody *S, + uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P, uint64_t SA, uint64_t ZA = 0, uint8_t *PairedLoc = nullptr) const = 0; virtual bool isGotRelative(uint32_t Type) const; Index: ELF/Target.cpp =================================================================== --- ELF/Target.cpp +++ ELF/Target.cpp @@ -17,6 +17,7 @@ #include "Target.h" #include "Error.h" +#include "InputFiles.h" #include "OutputSections.h" #include "Symbols.h" @@ -92,8 +93,9 @@ bool needsDynRelative(unsigned Type) const override; bool needsGot(uint32_t Type, const SymbolBody &S) const override; bool needsPlt(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, + void relocateOne(const InputFile *File, const SymbolBody *S, 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 canRelaxTls(unsigned Type, const SymbolBody *S) const override; unsigned relaxTls(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P, @@ -123,8 +125,9 @@ bool needsCopyRel(uint32_t Type, const SymbolBody &S) const override; bool needsGot(uint32_t Type, const SymbolBody &S) const override; bool needsPlt(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, + void relocateOne(const InputFile *File, const SymbolBody *S, 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; bool canRelaxTls(unsigned Type, const SymbolBody *S) const override; @@ -146,8 +149,9 @@ class PPCTargetInfo final : public TargetInfo { public: PPCTargetInfo(); - void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P, - uint64_t SA, uint64_t ZA = 0, + void relocateOne(const InputFile *File, const SymbolBody *S, 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; }; @@ -159,8 +163,9 @@ int32_t Index, unsigned RelOff) const override; bool needsGot(uint32_t Type, const SymbolBody &S) const override; bool needsPlt(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, + void relocateOne(const InputFile *File, const SymbolBody *S, 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; }; @@ -178,16 +183,18 @@ bool needsCopyRel(uint32_t Type, const SymbolBody &S) const override; bool needsGot(uint32_t Type, const SymbolBody &S) const override; bool needsPlt(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, + void relocateOne(const InputFile *File, const SymbolBody *S, 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; }; class AMDGPUTargetInfo final : public TargetInfo { public: AMDGPUTargetInfo() {} - void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P, - uint64_t SA, uint64_t ZA = 0, + void relocateOne(const InputFile *File, const SymbolBody *S, 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; }; @@ -198,8 +205,9 @@ void writeGotHeader(uint8_t *Buf) const override; bool needsGot(uint32_t Type, const SymbolBody &S) const override; bool needsPlt(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, + void relocateOne(const InputFile *File, const SymbolBody *S, 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 isHintRel(uint32_t Type) const override; bool isRelRelative(uint32_t Type) const override; @@ -396,7 +404,8 @@ return Type == R_386_GOTOFF; } -void X86TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, +void X86TargetInfo::relocateOne(const InputFile *File, const SymbolBody *S, + uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P, uint64_t SA, uint64_t ZA, uint8_t *PairedLoc) const { switch (Type) { @@ -477,7 +486,7 @@ // The next relocation should be against __tls_get_addr, so skip it return 1; case R_386_TLS_LDO_32: - relocateOne(Loc, BufEnd, R_386_TLS_LE, P, SA); + relocateOne(nullptr, nullptr, Loc, BufEnd, R_386_TLS_LE, P, SA); return 0; } llvm_unreachable("Unknown TLS optimization"); @@ -498,7 +507,7 @@ 0x03, 0x83, 0x00, 0x00, 0x00, 0x00 // addl 0(%ebx), %eax }; memcpy(Loc - 3, Inst, sizeof(Inst)); - relocateOne(Loc + 5, BufEnd, R_386_32, P, + relocateOne(nullptr, nullptr, Loc + 5, BufEnd, R_386_32, P, SA - Out::Got->getVA() - Out::Got->getNumEntries() * 4); } @@ -519,7 +528,7 @@ 0x81, 0xe8, 0x00, 0x00, 0x00, 0x00 // subl 0(%ebx), %eax }; memcpy(Loc - 3, Inst, sizeof(Inst)); - relocateOne(Loc + 5, BufEnd, R_386_32, P, + relocateOne(nullptr, nullptr, Loc + 5, BufEnd, R_386_32, P, Out::TlsPhdr->p_memsz - SA); } @@ -581,7 +590,7 @@ else *Op = 0x80 | Reg | (Reg << 3); } - relocateOne(Loc, BufEnd, R_386_TLS_LE, P, SA); + relocateOne(nullptr, nullptr, Loc, BufEnd, R_386_TLS_LE, P, SA); } X86_64TargetInfo::X86_64TargetInfo() { @@ -765,7 +774,7 @@ 0x48, 0x8d, 0x80, 0x00, 0x00, 0x00, 0x00 // lea x@tpoff,%rax }; memcpy(Loc - 4, Inst, sizeof(Inst)); - relocateOne(Loc + 8, BufEnd, R_X86_64_TPOFF32, P, SA); + relocateOne(nullptr, nullptr, Loc + 8, BufEnd, R_X86_64_TPOFF32, P, SA); } // "Ulrich Drepper, ELF Handling For Thread-Local Storage" (5.5 @@ -786,7 +795,7 @@ 0x48, 0x03, 0x05, 0x00, 0x00, 0x00, 0x00 // addq x@tpoff,%rax }; memcpy(Loc - 4, Inst, sizeof(Inst)); - relocateOne(Loc + 8, BufEnd, R_X86_64_TPOFF64, P + 12, SA); + relocateOne(nullptr, nullptr, Loc + 8, BufEnd, R_X86_64_TPOFF64, P + 12, SA); } // In some conditions, R_X86_64_GOTTPOFF relocation can be optimized to @@ -821,7 +830,7 @@ if (*Prefix == 0x4c) *Prefix = (IsMov || RspAdd) ? 0x49 : 0x4d; *RegSlot = (IsMov || RspAdd) ? (0xc0 | Reg) : (0x80 | Reg | (Reg << 3)); - relocateOne(Loc, BufEnd, R_X86_64_TPOFF32, P, SA); + relocateOne(nullptr, nullptr, Loc, BufEnd, R_X86_64_TPOFF32, P, SA); } // This function applies a TLS relocation with an optimization as described @@ -834,7 +843,7 @@ const SymbolBody *S) const { switch (Type) { case R_X86_64_DTPOFF32: - relocateOne(Loc, BufEnd, R_X86_64_TPOFF32, P, SA); + relocateOne(nullptr, nullptr, Loc, BufEnd, R_X86_64_TPOFF32, P, SA); return 0; case R_X86_64_GOTTPOFF: relocateTlsIeToLe(Loc, BufEnd, P, SA); @@ -855,7 +864,8 @@ llvm_unreachable("Unknown TLS optimization"); } -void X86_64TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, +void X86_64TargetInfo::relocateOne(const InputFile *File, const SymbolBody *S, + uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P, uint64_t SA, uint64_t ZA, uint8_t *PairedLoc) const { switch (Type) { @@ -918,7 +928,8 @@ PPCTargetInfo::PPCTargetInfo() {} bool PPCTargetInfo::isRelRelative(uint32_t Type) const { return false; } -void PPCTargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, +void PPCTargetInfo::relocateOne(const InputFile *File, const SymbolBody *S, + uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P, uint64_t SA, uint64_t ZA, uint8_t *PairedLoc) const { switch (Type) { @@ -1022,7 +1033,8 @@ } } -void PPC64TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, +void PPC64TargetInfo::relocateOne(const InputFile *File, const SymbolBody *S, + uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P, uint64_t SA, uint64_t ZA, uint8_t *PairedLoc) const { uint64_t TB = getPPC64TocBase(); @@ -1181,11 +1193,12 @@ uint64_t Got = Out::GotPlt->getVA(); uint64_t Plt = Out::Plt->getVA(); - relocateOne(Buf + 4, Buf + 8, R_AARCH64_ADR_PREL_PG_HI21, Plt + 4, Got + 16); - relocateOne(Buf + 8, Buf + 12, R_AARCH64_LDST64_ABS_LO12_NC, Plt + 8, - Got + 16); - relocateOne(Buf + 12, Buf + 16, R_AARCH64_ADD_ABS_LO12_NC, Plt + 12, - Got + 16); + relocateOne(nullptr, nullptr, Buf + 4, Buf + 8, R_AARCH64_ADR_PREL_PG_HI21, + Plt + 4, Got + 16); + relocateOne(nullptr, nullptr, Buf + 8, Buf + 12, R_AARCH64_LDST64_ABS_LO12_NC, + Plt + 8, Got + 16); + relocateOne(nullptr, nullptr, Buf + 12, Buf + 16, R_AARCH64_ADD_ABS_LO12_NC, + Plt + 12, Got + 16); } void AArch64TargetInfo::writePlt(uint8_t *Buf, uint64_t GotEntryAddr, @@ -1199,12 +1212,12 @@ }; memcpy(Buf, Inst, sizeof(Inst)); - relocateOne(Buf, Buf + 4, R_AARCH64_ADR_PREL_PG_HI21, PltEntryAddr, - GotEntryAddr); - relocateOne(Buf + 4, Buf + 8, R_AARCH64_LDST64_ABS_LO12_NC, PltEntryAddr + 4, - GotEntryAddr); - relocateOne(Buf + 8, Buf + 12, R_AARCH64_ADD_ABS_LO12_NC, PltEntryAddr + 8, - GotEntryAddr); + relocateOne(nullptr, nullptr, Buf, Buf + 4, R_AARCH64_ADR_PREL_PG_HI21, + PltEntryAddr, GotEntryAddr); + relocateOne(nullptr, nullptr, Buf + 4, Buf + 8, R_AARCH64_LDST64_ABS_LO12_NC, + PltEntryAddr + 4, GotEntryAddr); + relocateOne(nullptr, nullptr, Buf + 8, Buf + 12, R_AARCH64_ADD_ABS_LO12_NC, + PltEntryAddr + 8, GotEntryAddr); } unsigned AArch64TargetInfo::getTlsGotRel(unsigned Type) const { @@ -1282,7 +1295,8 @@ return Expr & (~static_cast(0xFFF)); } -void AArch64TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, +void AArch64TargetInfo::relocateOne(const InputFile *File, const SymbolBody *S, + uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P, uint64_t SA, uint64_t ZA, uint8_t *PairedLoc) const { switch (Type) { @@ -1382,7 +1396,8 @@ // 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, +void AMDGPUTargetInfo::relocateOne(const InputFile *File, const SymbolBody *S, + 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"); @@ -1453,9 +1468,11 @@ } template -void MipsTargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, - uint32_t Type, uint64_t P, uint64_t SA, - uint64_t ZA, uint8_t *PairedLoc) const { +void MipsTargetInfo::relocateOne(const InputFile *File, + const SymbolBody *S, uint8_t *Loc, + uint8_t *BufEnd, uint32_t Type, + uint64_t P, uint64_t SA, uint64_t ZA, + uint8_t *PairedLoc) const { const endianness E = ELFT::TargetEndianness; switch (Type) { case R_MIPS_32: @@ -1463,6 +1480,10 @@ break; case R_MIPS_CALL16: case R_MIPS_GOT16: { + // R_MIPS_GOT16 relocation against local symbol requires index of a local + // GOT entry which contains page address corresponds to the symbol address. + if (!S) + SA = Out::Got->getMipsLocalPageAddr(SA); int64_t V = SA - getMipsGpAddr(); if (Type == R_MIPS_GOT16) checkInt<16>(V, Type); @@ -1472,15 +1493,23 @@ case R_MIPS_GPREL16: { uint32_t Instr = read32(Loc); int64_t V = SA + SignExtend64<16>(Instr & 0xffff) - getMipsGpAddr(); + if (!S) + V += cast>(File)->getMipsGp0(); checkInt<16>(V, Type); write32(Loc, (Instr & 0xffff0000) | (V & 0xffff)); break; } - case R_MIPS_GPREL32: - write32(Loc, SA + int32_t(read32(Loc)) - getMipsGpAddr()); + case R_MIPS_GPREL32: { + int64_t V = SA + int32_t(read32(Loc)) - getMipsGpAddr(); + if (!S) + V += cast>(File)->getMipsGp0(); + write32(Loc, V); break; + } case R_MIPS_HI16: { uint32_t Instr = read32(Loc); + if (S == Config->MipsGpDisp) + SA = getMipsGpAddr() - P; if (PairedLoc) { uint64_t AHL = ((Instr & 0xffff) << 16) + SignExtend64<16>(read32(PairedLoc) & 0xffff); @@ -1496,6 +1525,8 @@ break; case R_MIPS_LO16: { uint32_t Instr = read32(Loc); + if (S == Config->MipsGpDisp) + SA = getMipsGpAddr() - P + 4; int64_t AHL = SignExtend64<16>(Instr & 0xffff); write32(Loc, (Instr & 0xffff0000) | ((SA + AHL) & 0xffff)); break;