forked from OSchip/llvm-project
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:
parent
246c1c47ea
commit
a6465bbb72
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue