Index: lld/trunk/ELF/OutputSections.cpp =================================================================== --- lld/trunk/ELF/OutputSections.cpp +++ lld/trunk/ELF/OutputSections.cpp @@ -146,7 +146,7 @@ template bool GotSection::addDynTlsEntry(SymbolBody &Sym) { if (Sym.hasGlobalDynIndex()) return false; - Sym.GlobalDynIndex = Target->GotHeaderEntriesNum + Entries.size(); + Sym.GlobalDynIndex = Entries.size(); // Global Dynamic TLS entries take two GOT slots. Entries.push_back(&Sym); Entries.push_back(nullptr); @@ -175,7 +175,9 @@ template typename GotSection::uintX_t GotSection::getMipsLocalEntryOffset(uintX_t EntryValue) { - size_t NewIndex = Target->GotHeaderEntriesNum + MipsLocalGotPos.size(); + // Take into account MIPS GOT header. + // See comment in the GotSection::writeTo. + size_t NewIndex = MipsLocalGotPos.size() + 2; auto P = MipsLocalGotPos.insert(std::make_pair(EntryValue, NewIndex)); assert(!P.second || MipsLocalGotPos.size() <= MipsLocalEntries); return P.first->second * sizeof(uintX_t) - MipsGPOffset; @@ -200,10 +202,14 @@ template unsigned GotSection::getMipsLocalEntriesNum() const { - return Target->GotHeaderEntriesNum + MipsLocalEntries; + return MipsLocalEntries; } template void GotSection::finalize() { + if (Config->EMachine == EM_MIPS) + // Take into account MIPS GOT header. + // See comment in the GotSection::writeTo. + MipsLocalEntries += 2; for (const OutputSectionBase *OutSec : MipsOutSections) { // Calculate an upper bound of MIPS GOT entries required to store page // addresses of local symbols. We assume the worst case - each 64kb @@ -212,18 +218,32 @@ // in the GOT entry is calculated as (value + 0x8000) & ~0xffff. MipsLocalEntries += (OutSec->getSize() + 0x8000 + 0xfffe) / 0xffff; } - this->Header.sh_size = - (Target->GotHeaderEntriesNum + MipsLocalEntries + Entries.size()) * - sizeof(uintX_t); + this->Header.sh_size = (MipsLocalEntries + Entries.size()) * sizeof(uintX_t); } template void GotSection::writeTo(uint8_t *Buf) { - Target->writeGotHeader(Buf); + if (Config->EMachine == EM_MIPS) { + // Set the MSB of the second GOT slot. This is not required by any + // MIPS ABI documentation, though. + // + // There is a comment in glibc saying that "The MSB of got[1] of a + // gnu object is set to identify gnu objects," and in GNU gold it + // says "the second entry will be used by some runtime loaders". + // But how this field is being used is unclear. + // + // We are not really willing to mimic other linkers behaviors + // without understanding why they do that, but because all files + // generated by GNU tools have this special GOT value, and because + // we've been doing this for years, it is probably a safe bet to + // keep doing this for now. We really need to revisit this to see + // if we had to do this. + auto *P = reinterpret_cast(Buf); + P[1] = uintX_t(1) << (ELFT::Is64Bits ? 63 : 31); + } for (std::pair &L : MipsLocalGotPos) { uint8_t *Entry = Buf + L.second * sizeof(uintX_t); write(Entry, L.first); } - Buf += Target->GotHeaderEntriesNum * sizeof(uintX_t); Buf += MipsLocalEntries * sizeof(uintX_t); for (const SymbolBody *B : Entries) { uint8_t *Entry = Buf; Index: lld/trunk/ELF/Target.h =================================================================== --- lld/trunk/ELF/Target.h +++ lld/trunk/ELF/Target.h @@ -29,7 +29,6 @@ virtual bool isTlsGlobalDynamicRel(uint32_t Type) const; virtual uint32_t getDynRel(uint32_t Type) const { return Type; } virtual uint32_t getTlsGotRel(uint32_t Type) const { return TlsGotRel; } - virtual void writeGotHeader(uint8_t *Buf) const {} virtual void writeGotPltHeader(uint8_t *Buf) const {} virtual void writeGotPlt(uint8_t *Buf, uint64_t Plt) const {}; virtual uint64_t getImplicitAddend(const uint8_t *Buf, uint32_t Type) const; @@ -85,7 +84,6 @@ uint32_t TlsOffsetRel; unsigned PltEntrySize = 8; unsigned PltZeroSize = 0; - unsigned GotHeaderEntriesNum = 0; unsigned GotPltHeaderEntriesNum = 3; uint32_t ThunkSize = 0; bool UseLazyBinding = false; Index: lld/trunk/ELF/Target.cpp =================================================================== --- lld/trunk/ELF/Target.cpp +++ lld/trunk/ELF/Target.cpp @@ -179,7 +179,6 @@ void writePltZero(uint8_t *Buf) const override; void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr, int32_t Index, unsigned RelOff) const override; - void writeGotHeader(uint8_t *Buf) const override; void writeThunk(uint8_t *Buf, uint64_t S) const override; bool needsThunk(uint32_t Type, const InputFile &File, const SymbolBody &S) const override; @@ -1294,7 +1293,6 @@ } template MipsTargetInfo::MipsTargetInfo() { - GotHeaderEntriesNum = 2; GotPltHeaderEntriesNum = 2; PageSize = 65536; PltEntrySize = 16; @@ -1353,29 +1351,6 @@ } template -void MipsTargetInfo::writeGotHeader(uint8_t *Buf) const { - typedef typename ELFT::Off Elf_Off; - typedef typename ELFT::uint uintX_t; - - // Set the MSB of the second GOT slot. This is not required by any - // MIPS ABI documentation, though. - // - // There is a comment in glibc saying that "The MSB of got[1] of a - // gnu object is set to identify gnu objects," and in GNU gold it - // says "the second entry will be used by some runtime loaders". - // But how this field is being used is unclear. - // - // We are not really willing to mimic other linkers behaviors - // without understanding why they do that, but because all files - // generated by GNU tools have this special GOT value, and because - // we've been doing this for years, it is probably a safe bet to - // keep doing this for now. We really need to revisit this to see - // if we had to do this. - auto *P = reinterpret_cast(Buf); - P[1] = uintX_t(1) << (ELFT::Is64Bits ? 63 : 31); -} - -template void MipsTargetInfo::writeGotPlt(uint8_t *Buf, uint64_t Plt) const { write32(Buf, Out::Plt->getVA()); }