Alternative way to detemplate GotSection.

GetSection is a template because write calls relocate.

relocate has two parts. The non alloc code really has to be a
template, as it is looking a raw input file data.

The alloc part is only a template because of getSize.

This patch folds the value of getSize early, detemplates
getRelocTargetVA and splits relocate into a templated non alloc case
and a regular function for the alloc case. This has the nice advantage
of making sure we collect all the information we need for relocations
before getting to InputSection::relocateNonAlloc.

Since we know got is alloc, it can just call the function directly and
avoid the template.

llvm-svn: 303355
This commit is contained in:
Rafael Espindola 2017-05-18 16:45:36 +00:00
parent 246c1c47ea
commit a6465bbb72
6 changed files with 46 additions and 46 deletions

View File

@ -404,10 +404,8 @@ static uint64_t getARMStaticBase(const SymbolBody &Body) {
return OS->FirstInPtLoad->Addr;
}
template <class ELFT>
static typename ELFT::uint
getRelocTargetVA(uint32_t Type, int64_t A, typename ELFT::uint P,
const SymbolBody &Body, RelExpr Expr) {
static uint64_t getRelocTargetVA(uint32_t Type, int64_t A, uint64_t P,
const SymbolBody &Body, RelExpr Expr) {
switch (Expr) {
case R_ABS:
case R_RELAX_GOT_PC_NOPIC:
@ -534,7 +532,7 @@ getRelocTargetVA(uint32_t Type, int64_t A, typename ELFT::uint P,
case R_NEG_TLS:
return Out::TlsPhdr->p_memsz - Body.getVA(A);
case R_SIZE:
return Body.getSize<ELFT>() + A;
return A; // Body.getSize was already folded into the addend.
case R_TLSDESC:
return InX::Got->getGlobalDynAddr(Body) + A;
case R_TLSDESC_PAGE:
@ -582,7 +580,7 @@ void InputSection::relocateNonAlloc(uint8_t *Buf, ArrayRef<RelTy> Rels) {
uint64_t SymVA = 0;
if (!Sym.isTls() || Out::TlsPhdr)
SymVA = SignExtend64<sizeof(typename ELFT::uint) * 8>(
getRelocTargetVA<ELFT>(Type, Addend, AddrLoc, Sym, R_ABS));
getRelocTargetVA(Type, Addend, AddrLoc, Sym, R_ABS));
Target->relocateOne(BufLoc, Type, SymVA);
}
}
@ -593,19 +591,28 @@ template <class ELFT> elf::ObjectFile<ELFT> *InputSectionBase::getFile() const {
template <class ELFT>
void InputSectionBase::relocate(uint8_t *Buf, uint8_t *BufEnd) {
if (Flags & SHF_ALLOC)
relocateAlloc(Buf, BufEnd);
else
relocateNonAlloc<ELFT>(Buf, BufEnd);
}
template <class ELFT>
void InputSectionBase::relocateNonAlloc(uint8_t *Buf, uint8_t *BufEnd) {
// scanReloc function in Writer.cpp constructs Relocations
// vector only for SHF_ALLOC'ed sections. For other sections,
// we handle relocations directly here.
auto *IS = dyn_cast<InputSection>(this);
if (IS && !(IS->Flags & SHF_ALLOC)) {
if (IS->AreRelocsRela)
IS->relocateNonAlloc<ELFT>(Buf, IS->template relas<ELFT>());
else
IS->relocateNonAlloc<ELFT>(Buf, IS->template rels<ELFT>());
return;
}
auto *IS = cast<InputSection>(this);
assert(!(IS->Flags & SHF_ALLOC));
if (IS->AreRelocsRela)
IS->relocateNonAlloc<ELFT>(Buf, IS->template relas<ELFT>());
else
IS->relocateNonAlloc<ELFT>(Buf, IS->template rels<ELFT>());
}
const unsigned Bits = sizeof(typename ELFT::uint) * 8;
void InputSectionBase::relocateAlloc(uint8_t *Buf, uint8_t *BufEnd) {
assert(Flags & SHF_ALLOC);
const unsigned Bits = Config->Wordsize * 8;
for (const Relocation &Rel : Relocations) {
uint64_t Offset = getOffset(Rel.Offset);
uint8_t *BufLoc = Buf + Offset;
@ -613,8 +620,8 @@ void InputSectionBase::relocate(uint8_t *Buf, uint8_t *BufEnd) {
uint64_t AddrLoc = getOutputSection()->Addr + Offset;
RelExpr Expr = Rel.Expr;
uint64_t TargetVA = SignExtend64<Bits>(
getRelocTargetVA<ELFT>(Type, Rel.Addend, AddrLoc, *Rel.Sym, Expr));
uint64_t TargetVA = SignExtend64(
getRelocTargetVA(Type, Rel.Addend, AddrLoc, *Rel.Sym, Expr), Bits);
switch (Expr) {
case R_RELAX_GOT_PC:

View File

@ -167,6 +167,8 @@ public:
template <class ELFT> std::string getObjMsg(uint64_t Offset);
template <class ELFT> void relocate(uint8_t *Buf, uint8_t *BufEnd);
void relocateAlloc(uint8_t *Buf, uint8_t *BufEnd);
template <class ELFT> void relocateNonAlloc(uint8_t *Buf, uint8_t *BufEnd);
std::vector<Relocation> Relocations;

View File

@ -935,6 +935,10 @@ static void scanRelocs(InputSectionBase &Sec, ArrayRef<RelTy> Rels) {
bool IsConstant =
isStaticLinkTimeConstant<ELFT>(Expr, Type, Body, Sec, Rel.r_offset);
// The size is not going to change, so we fold it in here.
if (Expr == R_SIZE)
Addend += Body.getSize<ELFT>();
// If the output being produced is position independent, the final value
// is still not known. In that case we still need some help from the
// dynamic linker. We can however do better than just copying the incoming

View File

@ -600,7 +600,7 @@ template <class ELFT> void EhFrameSection<ELFT>::writeTo(uint8_t *Buf) {
}
for (EhInputSection *S : Sections)
S->template relocate<ELFT>(Buf, nullptr);
S->relocateAlloc(Buf, nullptr);
// Construct .eh_frame_hdr. .eh_frame_hdr is a binary search table
// to get a FDE from an address to which FDE is applied. So here
@ -617,16 +617,16 @@ template <class ELFT> void EhFrameSection<ELFT>::writeTo(uint8_t *Buf) {
}
}
GotBaseSection::GotBaseSection()
GotSection::GotSection()
: SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS,
Target->GotEntrySize, ".got") {}
void GotBaseSection::addEntry(SymbolBody &Sym) {
void GotSection::addEntry(SymbolBody &Sym) {
Sym.GotIndex = NumEntries;
++NumEntries;
}
bool GotBaseSection::addDynTlsEntry(SymbolBody &Sym) {
bool GotSection::addDynTlsEntry(SymbolBody &Sym) {
if (Sym.GlobalDynIndex != -1U)
return false;
Sym.GlobalDynIndex = NumEntries;
@ -637,7 +637,7 @@ bool GotBaseSection::addDynTlsEntry(SymbolBody &Sym) {
// Reserves TLS entries for a TLS module ID and a TLS block offset.
// In total it takes two GOT slots.
bool GotBaseSection::addTlsIndex() {
bool GotSection::addTlsIndex() {
if (TlsIndexOff != uint32_t(-1))
return false;
TlsIndexOff = NumEntries * Config->Wordsize;
@ -645,27 +645,23 @@ bool GotBaseSection::addTlsIndex() {
return true;
}
uint64_t GotBaseSection::getGlobalDynAddr(const SymbolBody &B) const {
uint64_t GotSection::getGlobalDynAddr(const SymbolBody &B) const {
return this->getVA() + B.GlobalDynIndex * Config->Wordsize;
}
uint64_t GotBaseSection::getGlobalDynOffset(const SymbolBody &B) const {
uint64_t GotSection::getGlobalDynOffset(const SymbolBody &B) const {
return B.GlobalDynIndex * Config->Wordsize;
}
void GotBaseSection::finalizeContents() {
Size = NumEntries * Config->Wordsize;
}
void GotSection::finalizeContents() { Size = NumEntries * Config->Wordsize; }
bool GotBaseSection::empty() const {
bool GotSection::empty() const {
// If we have a relocation that is relative to GOT (such as GOTOFFREL),
// we need to emit a GOT even if it's empty.
return NumEntries == 0 && !HasGotOffRel;
}
template <class ELFT> void GotSection<ELFT>::writeTo(uint8_t *Buf) {
this->template relocate<ELFT>(Buf, Buf + Size);
}
void GotSection::writeTo(uint8_t *Buf) { relocateAlloc(Buf, Buf + Size); }
MipsGotSection::MipsGotSection()
: SyntheticSection(SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL, SHT_PROGBITS, 16,
@ -2242,7 +2238,7 @@ StringTableSection *InX::DynStrTab;
SymbolTableBaseSection *InX::DynSymTab;
InputSection *InX::Interp;
GdbIndexSection *InX::GdbIndex;
GotBaseSection *InX::Got;
GotSection *InX::Got;
GotPltSection *InX::GotPlt;
GnuHashTableSection *InX::GnuHashTab;
IgotPltSection *InX::IgotPlt;
@ -2284,11 +2280,6 @@ template class elf::MipsReginfoSection<ELF32BE>;
template class elf::MipsReginfoSection<ELF64LE>;
template class elf::MipsReginfoSection<ELF64BE>;
template class elf::GotSection<ELF32LE>;
template class elf::GotSection<ELF32BE>;
template class elf::GotSection<ELF64LE>;
template class elf::GotSection<ELF64BE>;
template class elf::DynamicSection<ELF32LE>;
template class elf::DynamicSection<ELF32BE>;
template class elf::DynamicSection<ELF64LE>;

View File

@ -104,12 +104,13 @@ private:
llvm::DenseMap<std::pair<ArrayRef<uint8_t>, SymbolBody *>, CieRecord> CieMap;
};
class GotBaseSection : public SyntheticSection {
class GotSection : public SyntheticSection {
public:
GotBaseSection();
GotSection();
size_t getSize() const override { return Size; }
void finalizeContents() override;
bool empty() const override;
void writeTo(uint8_t *Buf) override;
void addEntry(SymbolBody &Sym);
bool addDynTlsEntry(SymbolBody &Sym);
@ -130,11 +131,6 @@ protected:
uint64_t Size = 0;
};
template <class ELFT> class GotSection final : public GotBaseSection {
public:
void writeTo(uint8_t *Buf) override;
};
// .note.gnu.build-id section.
class BuildIdSection : public SyntheticSection {
// First 16 bytes are a header.
@ -764,7 +760,7 @@ struct InX {
static GnuHashTableSection *GnuHashTab;
static InputSection *Interp;
static GdbIndexSection *GdbIndex;
static GotBaseSection *Got;
static GotSection *Got;
static GotPltSection *GotPlt;
static IgotPltSection *IgotPlt;
static MipsGotSection *MipsGot;

View File

@ -403,7 +403,7 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() {
InX::MipsGot = make<MipsGotSection>();
Add(InX::MipsGot);
} else {
InX::Got = make<GotSection<ELFT>>();
InX::Got = make<GotSection>();
Add(InX::Got);
}