ELF: Teach SymbolBody about how to get its addresses.
Previously, the methods to get symbol addresses were somewhat scattered
in many places. You can use getEntryAddr returns the address of the symbol,
but if you want to get the GOT address for the symbol, you needed to call
Out<ELFT>::Got->getEntryAddr(Sym). This change adds new functions, getVA,
getGotVA, getGotPltVA, and getPltVA to SymbolBody, so that you can use
SymbolBody as the central place to ask about symbols.
http://reviews.llvm.org/D16710
llvm-svn: 259404
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index e60e905..d5ff181 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -173,9 +173,9 @@
if (!Body)
SymVA = getLocalRelTarget(*File, RI, 0);
else if (Target->needsGot(Type, *Body))
- SymVA = Out<ELFT>::Got->getEntryAddr(*Body);
+ SymVA = Body->getGotVA<ELFT>();
else
- SymVA = getSymVA<ELFT>(*Body);
+ SymVA = Body->getVA<ELFT>();
// By optimizing TLS relocations, it is sometimes needed to skip
// relocations that immediately follow TLS relocations. This function
// knows how many slots we need to skip.
@@ -213,9 +213,9 @@
continue;
}
- uintX_t SymVA = getSymVA<ELFT>(*Body);
+ uintX_t SymVA = Body->getVA<ELFT>();
if (Target->needsPlt(Type, *Body)) {
- SymVA = Out<ELFT>::Plt->getEntryAddr(*Body);
+ SymVA = Body->getPltVA<ELFT>();
} else if (Target->needsGot(Type, *Body)) {
if (Config->EMachine == EM_MIPS && needsMipsLocalGot(Type, Body))
// Under some conditions relocations against non-local symbols require
@@ -223,7 +223,7 @@
// initialized by full address of the symbol.
SymVA = Out<ELFT>::Got->getMipsLocalFullAddr(*Body);
else
- SymVA = Out<ELFT>::Got->getEntryAddr(*Body);
+ SymVA = Body->getGotVA<ELFT>();
if (Body->isTls())
Type = Target->getTlsGotRel(Type);
} else if (!Target->needsCopyRel(Type, *Body) &&
diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp
index ec17fe7..14194f7 100644
--- a/lld/ELF/OutputSections.cpp
+++ b/lld/ELF/OutputSections.cpp
@@ -47,12 +47,6 @@
return Entries.empty();
}
-template <class ELFT>
-typename GotPltSection<ELFT>::uintX_t
-GotPltSection<ELFT>::getEntryAddr(const SymbolBody &B) const {
- return this->getVA() + B.GotPltIndex * sizeof(uintX_t);
-}
-
template <class ELFT> void GotPltSection<ELFT>::finalize() {
this->Header.sh_size =
(Target->GotPltHeaderEntriesNum + Entries.size()) * sizeof(uintX_t);
@@ -62,7 +56,7 @@
Target->writeGotPltHeader(Buf);
Buf += Target->GotPltHeaderEntriesNum * sizeof(uintX_t);
for (const SymbolBody *B : Entries) {
- Target->writeGotPlt(Buf, Out<ELFT>::Plt->getEntryAddr(*B));
+ Target->writeGotPlt(Buf, B->getPltVA<ELFT>());
Buf += sizeof(uintX_t);
}
}
@@ -105,16 +99,8 @@
template <class ELFT>
typename GotSection<ELFT>::uintX_t
-GotSection<ELFT>::getEntryAddr(const SymbolBody &B) const {
- return this->getVA() +
- (Target->GotHeaderEntriesNum + MipsLocalEntries + B.GotIndex) *
- sizeof(uintX_t);
-}
-
-template <class ELFT>
-typename GotSection<ELFT>::uintX_t
GotSection<ELFT>::getMipsLocalFullAddr(const SymbolBody &B) {
- return getMipsLocalEntryAddr(getSymVA<ELFT>(B));
+ return getMipsLocalEntryAddr(B.getVA<ELFT>());
}
template <class ELFT>
@@ -176,7 +162,7 @@
// As the first approach, we can just store addresses for all symbols.
if (Config->EMachine != EM_MIPS && canBePreempted(B, false))
continue; // The dynamic linker will take care of it.
- uintX_t VA = getSymVA<ELFT>(*B);
+ uintX_t VA = B->getVA<ELFT>();
write<uintX_t, ELFT::TargetEndianness, sizeof(uintX_t)>(Entry, VA);
}
}
@@ -197,8 +183,8 @@
for (auto &I : Entries) {
const SymbolBody *B = I.first;
unsigned RelOff = I.second;
- uint64_t Got = Target->UseLazyBinding ? Out<ELFT>::GotPlt->getEntryAddr(*B)
- : Out<ELFT>::Got->getEntryAddr(*B);
+ uint64_t Got =
+ Target->UseLazyBinding ? B->getGotPltVA<ELFT>() : B->getGotVA<ELFT>();
uint64_t Plt = this->getVA() + Off;
Target->writePlt(Buf + Off, Got, Plt, B->PltIndex, RelOff);
Off += Target->PltEntrySize;
@@ -213,13 +199,6 @@
Entries.push_back(std::make_pair(Sym, RelOff));
}
-template <class ELFT>
-typename PltSection<ELFT>::uintX_t
-PltSection<ELFT>::getEntryAddr(const SymbolBody &B) const {
- return this->getVA() + Target->PltZeroSize +
- B.PltIndex * Target->PltEntrySize;
-}
-
template <class ELFT> void PltSection<ELFT>::finalize() {
this->Header.sh_size =
Target->PltZeroSize + Entries.size() * Target->PltEntrySize;
@@ -251,7 +230,7 @@
if (Target->canRelaxTls(Type, Body)) {
P->setSymbolAndType(Body->DynsymIndex, Target->getTlsGotRel(),
Config->Mips64EL);
- P->r_offset = Out<ELFT>::Got->getEntryAddr(*Body);
+ P->r_offset = Body->getGotVA<ELFT>();
return true;
}
@@ -312,9 +291,9 @@
if (!CBP && Body && isGnuIFunc<ELFT>(*Body)) {
P->setSymbolAndType(0, Target->IRelativeRel, Config->Mips64EL);
if (Out<ELFT>::GotPlt)
- P->r_offset = Out<ELFT>::GotPlt->getEntryAddr(*Body);
+ P->r_offset = Body->getGotPltVA<ELFT>();
else
- P->r_offset = Out<ELFT>::Got->getEntryAddr(*Body);
+ P->r_offset = Body->getGotVA<ELFT>();
continue;
}
@@ -333,9 +312,9 @@
P->setSymbolAndType(CBP ? Body->DynsymIndex : 0, Reloc, Config->Mips64EL);
if (LazyReloc)
- P->r_offset = Out<ELFT>::GotPlt->getEntryAddr(*Body);
+ P->r_offset = Body->getGotPltVA<ELFT>();
else if (NeedsGot)
- P->r_offset = Out<ELFT>::Got->getEntryAddr(*Body);
+ P->r_offset = Body->getGotVA<ELFT>();
else
P->r_offset = C.getOffset(RI.r_offset) + C.OutSec->getVA();
@@ -348,7 +327,7 @@
if (CBP)
S->r_addend = A;
else if (Body)
- S->r_addend = getSymVA<ELFT>(*Body) + A;
+ S->r_addend = Body->getVA<ELFT>() + A;
else
S->r_addend = getLocalRelTarget(File, R, A);
}
@@ -715,7 +694,7 @@
P->d_un.d_ptr = E.OutSec->getVA();
break;
case Entry::SymAddr:
- P->d_un.d_ptr = getSymVA<ELFT>(*E.Sym);
+ P->d_un.d_ptr = E.Sym->template getVA<ELFT>();
break;
case Entry::PlainInt:
P->d_un.d_val = E.Val;
@@ -835,48 +814,8 @@
this->Header.sh_size = Off;
}
-template <class ELFT>
-typename ELFFile<ELFT>::uintX_t elf2::getSymVA(const SymbolBody &S) {
- switch (S.kind()) {
- case SymbolBody::DefinedSyntheticKind: {
- auto &D = cast<DefinedSynthetic<ELFT>>(S);
- return D.Section.getVA() + D.Value;
- }
- case SymbolBody::DefinedRegularKind: {
- const auto &DR = cast<DefinedRegular<ELFT>>(S);
- InputSectionBase<ELFT> *SC = DR.Section;
- if (!SC)
- return DR.Sym.st_value;
-
- // Symbol offsets for AMDGPU need to be the offset in bytes of the symbol
- // from the beginning of the section.
- if (Config->EMachine == EM_AMDGPU)
- return SC->getOffset(DR.Sym);
- if (DR.Sym.getType() == STT_TLS)
- return SC->OutSec->getVA() + SC->getOffset(DR.Sym) -
- Out<ELFT>::TlsPhdr->p_vaddr;
- return SC->OutSec->getVA() + SC->getOffset(DR.Sym);
- }
- case SymbolBody::DefinedCommonKind:
- return Out<ELFT>::Bss->getVA() + cast<DefinedCommon>(S).OffsetInBss;
- case SymbolBody::SharedKind: {
- auto &SS = cast<SharedSymbol<ELFT>>(S);
- if (SS.NeedsCopy)
- return Out<ELFT>::Bss->getVA() + SS.OffsetInBss;
- return 0;
- }
- case SymbolBody::UndefinedElfKind:
- case SymbolBody::UndefinedKind:
- return 0;
- case SymbolBody::LazyKind:
- assert(S.isUsedInRegularObj() && "Lazy symbol reached writer");
- return 0;
- }
- llvm_unreachable("Invalid symbol kind");
-}
-
// Returns a VA which a relocatin RI refers to. Used only for local symbols.
-// For non-local symbols, use getSymVA instead.
+// For non-local symbols, use SymbolBody::getVA instead.
template <class ELFT, bool IsRela>
typename ELFFile<ELFT>::uintX_t
elf2::getLocalRelTarget(const ObjectFile<ELFT> &File,
@@ -1523,7 +1462,7 @@
ESym->setBindingAndType(getSymbolBinding(Body), Type);
ESym->st_size = Size;
ESym->setVisibility(Body->getVisibility());
- ESym->st_value = getSymVA<ELFT>(*Body);
+ ESym->st_value = Body->getVA<ELFT>();
if (OutSec)
ESym->st_shndx = OutSec->SectionIndex;
@@ -1650,11 +1589,6 @@
template class SymbolTableSection<ELF64LE>;
template class SymbolTableSection<ELF64BE>;
-template ELFFile<ELF32LE>::uintX_t getSymVA<ELF32LE>(const SymbolBody &);
-template ELFFile<ELF32BE>::uintX_t getSymVA<ELF32BE>(const SymbolBody &);
-template ELFFile<ELF64LE>::uintX_t getSymVA<ELF64LE>(const SymbolBody &);
-template ELFFile<ELF64BE>::uintX_t getSymVA<ELF64BE>(const SymbolBody &);
-
template uint32_t getLocalRelTarget(const ObjectFile<ELF32LE> &,
const ELFFile<ELF32LE>::Elf_Rel &,
uint32_t);
diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h
index 93bd997..7045720 100644
--- a/lld/ELF/OutputSections.h
+++ b/lld/ELF/OutputSections.h
@@ -47,9 +47,6 @@
return Rel.r_addend;
}
-template <class ELFT>
-typename llvm::object::ELFFile<ELFT>::uintX_t getSymVA(const SymbolBody &S);
-
template <class ELFT, bool IsRela>
typename llvm::object::ELFFile<ELFT>::uintX_t
getLocalRelTarget(const ObjectFile<ELFT> &File,
@@ -118,7 +115,6 @@
bool addDynTlsEntry(SymbolBody *Sym);
bool addCurrentModuleTlsIndex();
bool empty() const { return MipsLocalEntries == 0 && Entries.empty(); }
- uintX_t getEntryAddr(const SymbolBody &B) const;
uintX_t getMipsLocalFullAddr(const SymbolBody &B);
uintX_t getMipsLocalPageAddr(uintX_t Addr);
uintX_t getGlobalDynAddr(const SymbolBody &B) const;
@@ -155,7 +151,6 @@
void writeTo(uint8_t *Buf) override;
void addEntry(SymbolBody *Sym);
bool empty() const;
- uintX_t getEntryAddr(const SymbolBody &B) const;
private:
std::vector<const SymbolBody *> Entries;
@@ -171,7 +166,6 @@
void writeTo(uint8_t *Buf) override;
void addEntry(SymbolBody *Sym);
bool empty() const { return Entries.empty(); }
- uintX_t getEntryAddr(const SymbolBody &B) const;
private:
std::vector<std::pair<const SymbolBody *, unsigned>> Entries;
diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp
index ad6423f..6bc285c 100644
--- a/lld/ELF/Symbols.cpp
+++ b/lld/ELF/Symbols.cpp
@@ -8,9 +8,11 @@
//===----------------------------------------------------------------------===//
#include "Symbols.h"
-#include "InputSection.h"
#include "Error.h"
#include "InputFiles.h"
+#include "InputSection.h"
+#include "OutputSections.h"
+#include "Target.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Config/config.h"
@@ -26,6 +28,67 @@
using namespace lld;
using namespace lld::elf2;
+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;
+ }
+ case DefinedRegularKind: {
+ auto *D = cast<DefinedRegular<ELFT>>(this);
+ InputSectionBase<ELFT> *SC = D->Section;
+
+ // This is an absolute symbol.
+ if (!SC)
+ return D->Sym.st_value;
+
+ // Symbol offsets for AMDGPU need to be the offset in bytes of the symbol
+ // from the beginning of the section.
+ if (Config->EMachine == EM_AMDGPU)
+ return 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);
+ }
+ case DefinedCommonKind:
+ return Out<ELFT>::Bss->getVA() + cast<DefinedCommon>(this)->OffsetInBss;
+ case SharedKind: {
+ auto *SS = cast<SharedSymbol<ELFT>>(this);
+ if (SS->NeedsCopy)
+ return Out<ELFT>::Bss->getVA() + SS->OffsetInBss;
+ return 0;
+ }
+ case UndefinedElfKind:
+ case UndefinedKind:
+ return 0;
+ case LazyKind:
+ assert(isUsedInRegularObj() && "Lazy symbol reached writer");
+ return 0;
+ }
+ llvm_unreachable("Invalid symbol kind");
+}
+
+template <class ELFT>
+typename ELFFile<ELFT>::uintX_t SymbolBody::getGotVA() const {
+ return Out<ELFT>::Got->getVA() +
+ (Out<ELFT>::Got->getMipsLocalEntriesNum() + GotIndex) *
+ sizeof(typename ELFFile<ELFT>::uintX_t);
+}
+
+template <class ELFT>
+typename ELFFile<ELFT>::uintX_t SymbolBody::getGotPltVA() const {
+ return Out<ELFT>::GotPlt->getVA() +
+ GotPltIndex * sizeof(typename ELFFile<ELFT>::uintX_t);
+}
+
+template <class ELFT>
+typename ELFFile<ELFT>::uintX_t SymbolBody::getPltVA() const {
+ return Out<ELFT>::Plt->getVA() + Target->PltZeroSize +
+ PltIndex * Target->PltEntrySize;
+}
+
static uint8_t getMinVisibility(uint8_t VA, uint8_t VB) {
if (VA == STV_DEFAULT)
return VB;
@@ -166,6 +229,26 @@
#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 getGotVA<ELF32LE>() const;
+template uint32_t SymbolBody::template getGotVA<ELF32BE>() const;
+template uint64_t SymbolBody::template getGotVA<ELF64LE>() const;
+template uint64_t SymbolBody::template getGotVA<ELF64BE>() const;
+
+template uint32_t SymbolBody::template getGotPltVA<ELF32LE>() const;
+template uint32_t SymbolBody::template getGotPltVA<ELF32BE>() const;
+template uint64_t SymbolBody::template getGotPltVA<ELF64LE>() const;
+template uint64_t SymbolBody::template getGotPltVA<ELF64BE>() const;
+
+template uint32_t SymbolBody::template getPltVA<ELF32LE>() const;
+template uint32_t SymbolBody::template getPltVA<ELF32BE>() const;
+template uint64_t SymbolBody::template getPltVA<ELF64LE>() const;
+template uint64_t SymbolBody::template getPltVA<ELF64BE>() const;
+
template int SymbolBody::compare<ELF32LE>(SymbolBody *Other);
template int SymbolBody::compare<ELF32BE>(SymbolBody *Other);
template int SymbolBody::compare<ELF64LE>(SymbolBody *Other);
diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h
index f4be206..67cbaa3 100644
--- a/lld/ELF/Symbols.h
+++ b/lld/ELF/Symbols.h
@@ -101,6 +101,15 @@
bool isInGot() const { return GotIndex != -1U; }
bool isInPlt() const { return PltIndex != -1U; }
+ template <class ELFT>
+ typename llvm::object::ELFFile<ELFT>::uintX_t getVA() const;
+ template <class ELFT>
+ typename llvm::object::ELFFile<ELFT>::uintX_t getGotVA() const;
+ template <class ELFT>
+ typename llvm::object::ELFFile<ELFT>::uintX_t getGotPltVA() const;
+ template <class ELFT>
+ typename llvm::object::ELFFile<ELFT>::uintX_t getPltVA() const;
+
// A SymbolBody has a backreference to a Symbol. Originally they are
// doubly-linked. A backreference will never change. But the pointer
// in the Symbol may be mutated by the resolver. If you have a
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 8c31989..c65be55 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -1257,8 +1257,8 @@
template <class ELFT>
static typename ELFFile<ELFT>::uintX_t getEntryAddr() {
if (Config->EntrySym) {
- if (SymbolBody *E = Config->EntrySym->repl())
- return getSymVA<ELFT>(*E);
+ if (SymbolBody *B = Config->EntrySym->repl())
+ return B->getVA<ELFT>();
return 0;
}
if (Config->EntryAddr != uint64_t(-1))