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
This commit is contained in:
Rui Ueyama 2016-02-01 21:00:35 +00:00
parent 53907161cc
commit b5a6970ace
6 changed files with 114 additions and 94 deletions

View File

@ -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) &&

View File

@ -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);
}
}
@ -103,18 +97,10 @@ template <class ELFT> bool GotSection<ELFT>::addCurrentModuleTlsIndex() {
return true;
}
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);

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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))