Compute value of local symbol with getVA.
llvm-svn: 263225
This commit is contained in:
parent
ccb8b4d4fe
commit
87d9f10733
|
@ -171,48 +171,6 @@ InputSectionBase<ELFT>::findMipsPairedReloc(uint8_t *Buf, uint32_t SymIndex,
|
|||
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 <class ELFT, bool IsRela>
|
||||
static typename ELFFile<ELFT>::uintX_t
|
||||
getLocalRelTarget(const ObjectFile<ELFT> &File,
|
||||
const Elf_Rel_Impl<ELFT, IsRela> &RI,
|
||||
typename ELFFile<ELFT>::uintX_t Addend) {
|
||||
typedef typename ELFFile<ELFT>::Elf_Sym Elf_Sym;
|
||||
typedef typename ELFFile<ELFT>::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<ELFT> *Section = File.getSection(*Sym);
|
||||
|
||||
if (Sym->getType() == STT_TLS)
|
||||
return (Section->OutSec->getVA() + Section->getOffset(*Sym) + Addend) -
|
||||
Out<ELFT>::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<ELFT>::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 <class ELFT>
|
||||
template <bool isRela>
|
||||
void InputSectionBase<ELFT>::relocate(uint8_t *Buf, uint8_t *BufEnd,
|
||||
|
@ -244,7 +202,7 @@ void InputSectionBase<ELFT>::relocate(uint8_t *Buf, uint8_t *BufEnd,
|
|||
if (Target->canRelaxTls(Type, &Body)) {
|
||||
uintX_t SymVA;
|
||||
if (Body.isLocal())
|
||||
SymVA = getLocalRelTarget(*File, RI, 0);
|
||||
SymVA = Body.getVA<ELFT>();
|
||||
else if (Target->needsGot(Type, Body))
|
||||
SymVA = Body.getGotVA<ELFT>();
|
||||
else
|
||||
|
@ -256,11 +214,19 @@ void InputSectionBase<ELFT>::relocate(uint8_t *Buf, uint8_t *BufEnd,
|
|||
continue;
|
||||
}
|
||||
|
||||
// Handle relocations for local symbols -- they never get
|
||||
// resolved so we don't allocate a SymbolBody.
|
||||
uintX_t A = getAddend<ELFT>(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<ELFT>(A);
|
||||
uint8_t *PairedLoc = nullptr;
|
||||
if (Config->EMachine == EM_MIPS) {
|
||||
if (Type == R_MIPS_GPREL16 || Type == R_MIPS_GPREL32)
|
||||
|
|
|
@ -266,21 +266,12 @@ template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) {
|
|||
SymbolBody *Sym = Rel.Sym;
|
||||
|
||||
if (IsRela) {
|
||||
uintX_t VA = 0;
|
||||
uintX_t Addend = Rel.Addend;
|
||||
if (Rel.UseSymVA) {
|
||||
if (auto *L = dyn_cast<LocalSymbol<ELFT>>(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<ELFT>();
|
||||
}
|
||||
}
|
||||
reinterpret_cast<Elf_Rela *>(P)->r_addend = Addend + VA;
|
||||
uintX_t VA;
|
||||
if (Rel.UseSymVA)
|
||||
VA = Sym->getVA<ELFT>(Rel.Addend);
|
||||
else
|
||||
VA = Rel.Addend;
|
||||
reinterpret_cast<Elf_Rela *>(P)->r_addend = VA;
|
||||
}
|
||||
|
||||
P->r_offset = Rel.getOffset();
|
||||
|
|
|
@ -29,51 +29,80 @@ using namespace lld;
|
|||
using namespace lld::elf;
|
||||
|
||||
template <class ELFT>
|
||||
typename ELFFile<ELFT>::uintX_t SymbolBody::getVA() const {
|
||||
switch (kind()) {
|
||||
case DefinedSyntheticKind: {
|
||||
auto *D = cast<DefinedSynthetic<ELFT>>(this);
|
||||
return D->Section.getVA() + D->Value;
|
||||
static typename ELFFile<ELFT>::uintX_t
|
||||
getSymVA(const SymbolBody &Body, typename ELFFile<ELFT>::uintX_t &Addend) {
|
||||
typedef typename ELFFile<ELFT>::Elf_Sym Elf_Sym;
|
||||
typedef typename ELFFile<ELFT>::uintX_t uintX_t;
|
||||
|
||||
switch (Body.kind()) {
|
||||
case SymbolBody::DefinedSyntheticKind: {
|
||||
auto &D = cast<DefinedSynthetic<ELFT>>(Body);
|
||||
return D.Section.getVA() + D.Value;
|
||||
}
|
||||
case DefinedRegularKind: {
|
||||
auto *D = cast<DefinedRegular<ELFT>>(this);
|
||||
InputSectionBase<ELFT> *SC = D->Section;
|
||||
case SymbolBody::DefinedRegularKind: {
|
||||
auto &D = cast<DefinedRegular<ELFT>>(Body);
|
||||
InputSectionBase<ELFT> *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<ELFT>::TlsPhdr->p_vaddr;
|
||||
return SC->OutSec->getVA() + SC->getOffset(D->Sym);
|
||||
return SC->OutSec->getVA() + SC->getOffset(D.Sym);
|
||||
}
|
||||
case DefinedCommonKind:
|
||||
return Out<ELFT>::Bss->getVA() + cast<DefinedCommon>(this)->OffsetInBss;
|
||||
case SharedKind: {
|
||||
auto *SS = cast<SharedSymbol<ELFT>>(this);
|
||||
if (!SS->NeedsCopyOrPltAddr)
|
||||
case SymbolBody::DefinedCommonKind:
|
||||
return Out<ELFT>::Bss->getVA() + cast<DefinedCommon>(Body).OffsetInBss;
|
||||
case SymbolBody::SharedKind: {
|
||||
auto &SS = cast<SharedSymbol<ELFT>>(Body);
|
||||
if (!SS.NeedsCopyOrPltAddr)
|
||||
return 0;
|
||||
if (SS->IsFunc)
|
||||
return getPltVA<ELFT>();
|
||||
if (SS.IsFunc)
|
||||
return Body.getPltVA<ELFT>();
|
||||
else
|
||||
return Out<ELFT>::Bss->getVA() + SS->OffsetInBss;
|
||||
return Out<ELFT>::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<LocalSymbol<ELFT>>(Body);
|
||||
InputSectionBase<ELFT> *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<ELFT>::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<ELFT>::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 <class ELFT>
|
||||
typename ELFFile<ELFT>::uintX_t
|
||||
SymbolBody::getVA(typename ELFFile<ELFT>::uintX_t Addend) const {
|
||||
return getSymVA<ELFT>(*this, Addend) + Addend;
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
typename ELFFile<ELFT>::uintX_t SymbolBody::getGotVA() const {
|
||||
return Out<ELFT>::Got->getVA() +
|
||||
|
@ -231,10 +260,10 @@ std::string elf::demangle(StringRef Name) {
|
|||
#endif
|
||||
}
|
||||
|
||||
template uint32_t SymbolBody::template getVA<ELF32LE>() const;
|
||||
template uint32_t SymbolBody::template getVA<ELF32BE>() const;
|
||||
template uint64_t SymbolBody::template getVA<ELF64LE>() const;
|
||||
template uint64_t SymbolBody::template getVA<ELF64BE>() const;
|
||||
template uint32_t SymbolBody::template getVA<ELF32LE>(uint32_t) const;
|
||||
template uint32_t SymbolBody::template getVA<ELF32BE>(uint32_t) const;
|
||||
template uint64_t SymbolBody::template getVA<ELF64LE>(uint64_t) const;
|
||||
template uint64_t SymbolBody::template getVA<ELF64BE>(uint64_t) const;
|
||||
|
||||
template uint32_t SymbolBody::template getGotVA<ELF32LE>() const;
|
||||
template uint32_t SymbolBody::template getGotVA<ELF32BE>() const;
|
||||
|
|
|
@ -98,7 +98,8 @@ public:
|
|||
bool isInPlt() const { return PltIndex != -1U; }
|
||||
|
||||
template <class ELFT>
|
||||
typename llvm::object::ELFFile<ELFT>::uintX_t getVA() const;
|
||||
typename llvm::object::ELFFile<ELFT>::uintX_t
|
||||
getVA(typename llvm::object::ELFFile<ELFT>::uintX_t Addend = 0) const;
|
||||
template <class ELFT>
|
||||
typename llvm::object::ELFFile<ELFT>::uintX_t getGotVA() const;
|
||||
template <class ELFT>
|
||||
|
|
Loading…
Reference in New Issue