summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/ELF/InputSection.cpp10
-rw-r--r--lld/ELF/OutputSections.cpp94
-rw-r--r--lld/ELF/OutputSections.h6
-rw-r--r--lld/ELF/Symbols.cpp85
-rw-r--r--lld/ELF/Symbols.h9
-rw-r--r--lld/ELF/Writer.cpp4
6 files changed, 114 insertions, 94 deletions
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index e60e9052808..d5ff181b4f9 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -173,9 +173,9 @@ void InputSectionBase<ELFT>::relocate(uint8_t *Buf, uint8_t *BufEnd,
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 @@ void InputSectionBase<ELFT>::relocate(uint8_t *Buf, uint8_t *BufEnd,
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 @@ void InputSectionBase<ELFT>::relocate(uint8_t *Buf, uint8_t *BufEnd,
// 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 ec17fe75ed5..14194f73666 100644
--- a/lld/ELF/OutputSections.cpp
+++ b/lld/ELF/OutputSections.cpp
@@ -47,12 +47,6 @@ template <class ELFT> bool GotPltSection<ELFT>::empty() const {
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 @@ template <class ELFT> void GotPltSection<ELFT>::writeTo(uint8_t *Buf) {
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> bool GotSection<ELFT>::addCurrentModuleTlsIndex() {
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 @@ template <class ELFT> void GotSection<ELFT>::writeTo(uint8_t *Buf) {
// 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 @@ template <class ELFT> void PltSection<ELFT>::writeTo(uint8_t *Buf) {
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 @@ template <class ELFT> void PltSection<ELFT>::addEntry(SymbolBody *Sym) {
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 @@ bool RelocationSection<ELFT>::applyTlsDynamicReloc(SymbolBody *Body,
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 @@ template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) {
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 @@ template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) {
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 @@ template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) {
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 @@ template <class ELFT> void DynamicSection<ELFT>::writeTo(uint8_t *Buf) {
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 @@ void OutputSection<ELFT>::addSection(InputSectionBase<ELFT> *C) {
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 @@ void SymbolTableSection<ELFT>::writeGlobalSymbols(uint8_t *Buf) {
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<ELF32BE>;
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 93bd997c3b3..7045720bf45 100644
--- a/lld/ELF/OutputSections.h
+++ b/lld/ELF/OutputSections.h
@@ -47,9 +47,6 @@ getAddend(const typename llvm::object::ELFFile<ELFT>::Elf_Rela &Rel) {
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 @@ public:
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 @@ public:
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 @@ public:
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 ad6423f5e93..6bc285ce513 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 llvm::ELF;
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 @@ std::string elf2::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 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 f4be2061a48..67cbaa327f3 100644
--- a/lld/ELF/Symbols.h
+++ b/lld/ELF/Symbols.h
@@ -101,6 +101,15 @@ public:
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 8c31989c88c..c65be556ba1 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -1257,8 +1257,8 @@ static uint32_t getELFFlags() {
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))
OpenPOWER on IntegriCloud