Index: ELF/InputSection.cpp =================================================================== --- ELF/InputSection.cpp +++ ELF/InputSection.cpp @@ -171,48 +171,6 @@ return nullptr; } -// Returns a VA which a relocatin RI refers to. Used only for local symbols. -// For non-local symbols, use SymbolBody::getVA instead. -template -static typename ELFFile::uintX_t -getLocalRelTarget(const ObjectFile &File, - const Elf_Rel_Impl &RI, - typename ELFFile::uintX_t Addend) { - typedef typename ELFFile::Elf_Sym Elf_Sym; - typedef typename ELFFile::uintX_t uintX_t; - - // PPC64 has a special relocation representing the TOC base pointer - // that does not have a corresponding symbol. - if (Config->EMachine == EM_PPC64 && RI.getType(false) == R_PPC64_TOC) - return getPPC64TocBase() + Addend; - - const Elf_Sym *Sym = - File.getObj().getRelocationSymbol(&RI, File.getSymbolTable()); - - if (!Sym) - fatal("Unsupported relocation without symbol"); - - InputSectionBase *Section = File.getSection(*Sym); - - if (Sym->getType() == STT_TLS) - return (Section->OutSec->getVA() + Section->getOffset(*Sym) + Addend) - - Out::TlsPhdr->p_vaddr; - - // According to the ELF spec reference to a local symbol from outside - // the group are not allowed. Unfortunately .eh_frame breaks that rule - // and must be treated specially. For now we just replace the symbol with - // 0. - if (Section == InputSection::Discarded || !Section->Live) - return Addend; - - uintX_t Offset = Sym->st_value; - if (Sym->getType() == STT_SECTION) { - Offset += Addend; - Addend = 0; - } - return Section->OutSec->getVA() + Section->getOffset(Offset) + Addend; -} - template template void InputSectionBase::relocate(uint8_t *Buf, uint8_t *BufEnd, @@ -244,7 +202,7 @@ if (Target->canRelaxTls(Type, &Body)) { uintX_t SymVA; if (Body.isLocal()) - SymVA = getLocalRelTarget(*File, RI, 0); + SymVA = Body.getVA(); else if (Target->needsGot(Type, Body)) SymVA = Body.getGotVA(); else @@ -256,11 +214,19 @@ continue; } - // Handle relocations for local symbols -- they never get - // resolved so we don't allocate a SymbolBody. uintX_t A = getAddend(RI); + + // PPC64 has a special relocation representing the TOC base pointer + // that does not have a corresponding symbol. + if (Config->EMachine == EM_PPC64 && RI.getType(false) == R_PPC64_TOC) { + uintX_t SymVA = getPPC64TocBase() + A; + Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc, SymVA, 0); + continue; + } + + // Handle relocations for local symbols. if (Body.isLocal()) { - uintX_t SymVA = getLocalRelTarget(*File, RI, A); + uintX_t SymVA = Body.getVA(A); uint8_t *PairedLoc = nullptr; if (Config->EMachine == EM_MIPS) { if (Type == R_MIPS_GPREL16 || Type == R_MIPS_GPREL32) Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -265,21 +265,12 @@ SymbolBody *Sym = Rel.Sym; if (IsRela) { - uintX_t VA = 0; - uintX_t Addend = Rel.Addend; - if (Rel.UseSymVA) { - if (auto *L = dyn_cast>(Sym)) { - uintX_t Pos = L->Sym.st_value; - if (L->Sym.getType() == STT_SECTION) { - Pos += Addend; - Addend = 0; - } - VA = L->Section->OutSec->getVA() + L->Section->getOffset(Pos); - } else { - VA = Sym->getVA(); - } - } - reinterpret_cast(P)->r_addend = Addend + VA; + uintX_t VA; + if (Rel.UseSymVA) + VA = Sym->getVA(Rel.Addend); + else + VA = Rel.Addend; + reinterpret_cast(P)->r_addend = VA; } P->r_offset = Rel.getOffset(); Index: ELF/Symbols.h =================================================================== --- ELF/Symbols.h +++ ELF/Symbols.h @@ -101,7 +101,8 @@ bool isInPlt() const { return PltIndex != -1U; } template - typename llvm::object::ELFFile::uintX_t getVA() const; + typename llvm::object::ELFFile::uintX_t + getVA(typename llvm::object::ELFFile::uintX_t Addend = 0) const; template typename llvm::object::ELFFile::uintX_t getGotVA() const; template Index: ELF/Symbols.cpp =================================================================== --- ELF/Symbols.cpp +++ ELF/Symbols.cpp @@ -29,52 +29,81 @@ using namespace lld::elf; template -typename ELFFile::uintX_t SymbolBody::getVA() const { - switch (kind()) { - case DefinedSyntheticKind: { - auto *D = cast>(this); - return D->Section.getVA() + D->Value; +static typename ELFFile::uintX_t +getSymVA(const SymbolBody &Body, typename ELFFile::uintX_t &Addend) { + typedef typename ELFFile::Elf_Sym Elf_Sym; + typedef typename ELFFile::uintX_t uintX_t; + + switch (Body.kind()) { + case SymbolBody::DefinedSyntheticKind: { + auto &D = cast>(Body); + return D.Section.getVA() + D.Value; } - case DefinedRegularKind: { - auto *D = cast>(this); - InputSectionBase *SC = D->Section; + case SymbolBody::DefinedRegularKind: { + auto &D = cast>(Body); + InputSectionBase *SC = D.Section; // This is an absolute symbol. if (!SC) - return D->Sym.st_value; + return D.Sym.st_value; assert(SC->Live); - if (D->Sym.getType() == STT_TLS) - return SC->OutSec->getVA() + SC->getOffset(D->Sym) - + if (D.Sym.getType() == STT_TLS) + return SC->OutSec->getVA() + SC->getOffset(D.Sym) - Out::TlsPhdr->p_vaddr; - return SC->OutSec->getVA() + SC->getOffset(D->Sym); + return SC->OutSec->getVA() + SC->getOffset(D.Sym); } - case DefinedCommonKind: - return Out::Bss->getVA() + cast(this)->OffsetInBss; - case SharedKind: { - auto *SS = cast>(this); - if (!SS->NeedsCopyOrPltAddr) + case SymbolBody::DefinedCommonKind: + return Out::Bss->getVA() + cast(Body).OffsetInBss; + case SymbolBody::SharedKind: { + auto &SS = cast>(Body); + if (!SS.NeedsCopyOrPltAddr) return 0; - if (SS->IsFunc) - return getPltVA(); + if (SS.IsFunc) + return Body.getPltVA(); else - return Out::Bss->getVA() + SS->OffsetInBss; + return Out::Bss->getVA() + SS.OffsetInBss; } - case UndefinedElfKind: - case UndefinedKind: + case SymbolBody::UndefinedElfKind: + case SymbolBody::UndefinedKind: return 0; - case LazyKind: - assert(isUsedInRegularObj() && "Lazy symbol reached writer"); + case SymbolBody::LazyKind: + assert(Body.isUsedInRegularObj() && "Lazy symbol reached writer"); return 0; - case DefinedBitcodeKind: + case SymbolBody::DefinedBitcodeKind: llvm_unreachable("Should have been replaced"); - case DefinedLocalKind: - llvm_unreachable("Should not be used"); + case SymbolBody::DefinedLocalKind: { + auto &L = cast>(Body); + InputSectionBase *SC = L.Section; + + // According to the ELF spec reference to a local symbol from outside the + // group are not allowed. Unfortunately .eh_frame breaks that rule and must + // be treated specially. For now we just replace the symbol with 0. + if (SC == InputSection::Discarded || !SC->Live) + return 0; + + const Elf_Sym &Sym = L.Sym; + uintX_t Offset = Sym.st_value; + if (Sym.getType() == STT_TLS) + return (SC->OutSec->getVA() + SC->getOffset(Sym) + Addend) - + Out::TlsPhdr->p_vaddr; + if (Sym.getType() == STT_SECTION) { + Offset += Addend; + Addend = 0; + } + return SC->OutSec->getVA() + SC->getOffset(Offset); + } } llvm_unreachable("Invalid symbol kind"); } template +typename ELFFile::uintX_t +SymbolBody::getVA(typename ELFFile::uintX_t Addend) const { + return getSymVA(*this, Addend) + Addend; +} + +template typename ELFFile::uintX_t SymbolBody::getGotVA() const { return Out::Got->getVA() + (Out::Got->getMipsLocalEntriesNum() + GotIndex) * @@ -239,10 +268,10 @@ #endif } -template uint32_t SymbolBody::template getVA() const; -template uint32_t SymbolBody::template getVA() const; -template uint64_t SymbolBody::template getVA() const; -template uint64_t SymbolBody::template getVA() const; +template uint32_t SymbolBody::template getVA(uint32_t) const; +template uint32_t SymbolBody::template getVA(uint32_t) const; +template uint64_t SymbolBody::template getVA(uint64_t) const; +template uint64_t SymbolBody::template getVA(uint64_t) const; template uint32_t SymbolBody::template getGotVA() const; template uint32_t SymbolBody::template getGotVA() const;