Index: ELF/InputSection.h =================================================================== --- ELF/InputSection.h +++ ELF/InputSection.h @@ -167,6 +167,8 @@ template std::string getObjMsg(uint64_t Offset); template void relocate(uint8_t *Buf, uint8_t *BufEnd); + void relocateAlloc(uint8_t *Buf, uint8_t *BufEnd); + template void relocateNonAlloc(uint8_t *Buf, uint8_t *BufEnd); std::vector Relocations; Index: ELF/InputSection.cpp =================================================================== --- ELF/InputSection.cpp +++ ELF/InputSection.cpp @@ -390,10 +390,8 @@ } } -template -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: @@ -518,7 +516,7 @@ case R_NEG_TLS: return Out::TlsPhdr->p_memsz - Body.getVA(A); case R_SIZE: - return Body.getSize() + A; + return A; // Body.getSize was already folded into the addend. case R_TLSDESC: return InX::Got->getGlobalDynAddr(Body) + A; case R_TLSDESC_PAGE: @@ -566,7 +564,7 @@ uint64_t SymVA = 0; if (!Sym.isTls() || Out::TlsPhdr) SymVA = SignExtend64( - getRelocTargetVA(Type, Addend, AddrLoc, Sym, R_ABS)); + getRelocTargetVA(Type, Addend, AddrLoc, Sym, R_ABS)); Target->relocateOne(BufLoc, Type, SymVA); } } @@ -577,19 +575,28 @@ template void InputSectionBase::relocate(uint8_t *Buf, uint8_t *BufEnd) { + if (Flags & SHF_ALLOC) + relocateAlloc(Buf, BufEnd); + else + relocateNonAlloc(Buf, BufEnd); +} + +template +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(this); - if (IS && !(IS->Flags & SHF_ALLOC)) { - if (IS->AreRelocsRela) - IS->relocateNonAlloc(Buf, IS->template relas()); - else - IS->relocateNonAlloc(Buf, IS->template rels()); - return; - } + auto *IS = cast(this); + assert(!(IS->Flags & SHF_ALLOC)); + if (IS->AreRelocsRela) + IS->relocateNonAlloc(Buf, IS->template relas()); + else + IS->relocateNonAlloc(Buf, IS->template rels()); +} - 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; @@ -597,8 +604,8 @@ uint64_t AddrLoc = getOutputSection()->Addr + Offset; RelExpr Expr = Rel.Expr; - uint64_t TargetVA = SignExtend64( - getRelocTargetVA(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: Index: ELF/Relocations.cpp =================================================================== --- ELF/Relocations.cpp +++ ELF/Relocations.cpp @@ -935,6 +935,10 @@ bool IsConstant = isStaticLinkTimeConstant(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(); + // 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 Index: ELF/SyntheticSections.h =================================================================== --- ELF/SyntheticSections.h +++ ELF/SyntheticSections.h @@ -104,12 +104,13 @@ llvm::DenseMap, 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 @@ uint64_t Size = 0; }; -template 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 @@ static GnuHashTableSection *GnuHashTab; static InputSection *Interp; static GdbIndexSection *GdbIndex; - static GotBaseSection *Got; + static GotSection *Got; static GotPltSection *GotPlt; static IgotPltSection *IgotPlt; static MipsGotSection *MipsGot; Index: ELF/SyntheticSections.cpp =================================================================== --- ELF/SyntheticSections.cpp +++ ELF/SyntheticSections.cpp @@ -600,7 +600,7 @@ } for (EhInputSection *S : Sections) - S->template relocate(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 @@ } } -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 @@ // 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 @@ 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 void GotSection::writeTo(uint8_t *Buf) { - this->template relocate(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 @@ 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; template class elf::MipsReginfoSection; -template class elf::GotSection; -template class elf::GotSection; -template class elf::GotSection; -template class elf::GotSection; - template class elf::DynamicSection; template class elf::DynamicSection; template class elf::DynamicSection; Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -403,7 +403,7 @@ InX::MipsGot = make(); Add(InX::MipsGot); } else { - InX::Got = make>(); + InX::Got = make(); Add(InX::Got); }