From: Simon Atanasyan Date: Wed, 16 Nov 2016 21:01:02 +0000 (+0000) Subject: [ELF][MIPS] Add MipsGotSection to handle MIPS GOT X-Git-Tag: llvmorg-4.0.0-rc1~4377 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=725dc14bb21da8a01709a6b3370a658d071689dc;p=platform%2Fupstream%2Fllvm.git [ELF][MIPS] Add MipsGotSection to handle MIPS GOT MIPS GOT handling is very different from other targets so it is better to keep the code in the separatre section class MipsGotSection. This patch introduces the new section and moves all MIPS specific code from GotSection to the new class. I did not rename fields and methods in the MipsGotSection class to reduce the diff and plan to do that by the separate commit. Differential revision: https://reviews.llvm.org/D26733 llvm-svn: 287150 --- diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 28e1d71..7cec93d 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -382,19 +382,21 @@ static typename ELFT::uint getSymVA(uint32_t Type, typename ELFT::uint A, // If relocation against MIPS local symbol requires GOT entry, this entry // should be initialized by 'page address'. This address is high 16-bits // of sum the symbol's value and the addend. - return In::Got->getMipsLocalPageOffset(Body.getVA(A)); + return In::MipsGot->getMipsLocalPageOffset(Body.getVA(A)); case R_MIPS_GOT_OFF: case R_MIPS_GOT_OFF32: // In case of MIPS if a GOT relocation has non-zero addend this addend // should be applied to the GOT entry content not to the GOT entry offset. // That is why we use separate expression type. - return In::Got->getMipsGotOffset(Body, A); + return In::MipsGot->getMipsGotOffset(Body, A); + case R_MIPS_GOTREL: + return Body.getVA(A) - In::MipsGot->getVA() - MipsGPOffset; case R_MIPS_TLSGD: - return In::Got->getGlobalDynOffset(Body) + - In::Got->getMipsTlsOffset() - MipsGPOffset; + return In::MipsGot->getGlobalDynOffset(Body) + + In::MipsGot->getMipsTlsOffset() - MipsGPOffset; case R_MIPS_TLSLD: - return In::Got->getTlsIndexOff() + In::Got->getMipsTlsOffset() - - MipsGPOffset; + return In::MipsGot->getTlsIndexOff() + + In::MipsGot->getMipsTlsOffset() - MipsGPOffset; case R_PPC_OPD: { uint64_t SymVA = Body.getVA(A); // If we have an undefined weak symbol, we might get here with a symbol diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index f68c9cf..c402bce 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -94,30 +94,26 @@ static bool isPreemptible(const SymbolBody &Body, uint32_t Type) { // relocation even for non-preemptible symbols in applications. For static // linking support we must either resolve the module index relocation at static // link time, or hard code the module index (1) for the application in the GOT. -template -static unsigned handleNoRelaxTlsRelocation(uint32_t Type, SymbolBody &Body, - InputSectionBase &C, - typename ELFT::uint Offset, - typename ELFT::uint Addend, - RelExpr Expr) { +template +static unsigned handleNoRelaxTlsRelocation( + GOT *Got, uint32_t Type, SymbolBody &Body, InputSectionBase &C, + typename ELFT::uint Offset, typename ELFT::uint Addend, RelExpr Expr) { if (Expr == R_MIPS_TLSLD || Expr == R_TLSLD_PC) { - if (In::Got->addTlsIndex() && - (Config->Pic || Config->EMachine == EM_ARM)) - In::RelaDyn->addReloc({Target->TlsModuleIndexRel, In::Got, - In::Got->getTlsIndexOff(), false, - nullptr, 0}); + if (Got->addTlsIndex() && (Config->Pic || Config->EMachine == EM_ARM)) + In::RelaDyn->addReloc({Target->TlsModuleIndexRel, Got, + Got->getTlsIndexOff(), false, nullptr, 0}); C.Relocations.push_back({Expr, Type, Offset, Addend, &Body}); return 1; } typedef typename ELFT::uint uintX_t; if (Target->isTlsGlobalDynamicRel(Type)) { - if (In::Got->addDynTlsEntry(Body) && + if (Got->addDynTlsEntry(Body) && (Body.isPreemptible() || Config->EMachine == EM_ARM)) { - uintX_t Off = In::Got->getGlobalDynOffset(Body); + uintX_t Off = Got->getGlobalDynOffset(Body); In::RelaDyn->addReloc( - {Target->TlsModuleIndexRel, In::Got, Off, false, &Body, 0}); + {Target->TlsModuleIndexRel, Got, Off, false, &Body, 0}); if (Body.isPreemptible()) - In::RelaDyn->addReloc({Target->TlsOffsetRel, In::Got, + In::RelaDyn->addReloc({Target->TlsOffsetRel, Got, Off + (uintX_t)sizeof(uintX_t), false, &Body, 0}); } @@ -141,9 +137,12 @@ static unsigned handleTlsRelocation(uint32_t Type, SymbolBody &Body, typedef typename ELFT::uint uintX_t; - if (Config->EMachine == EM_MIPS || Config->EMachine == EM_ARM) - return handleNoRelaxTlsRelocation(Type, Body, C, Offset, Addend, - Expr); + if (Config->EMachine == EM_ARM) + return handleNoRelaxTlsRelocation(In::Got, Type, Body, C, + Offset, Addend, Expr); + if (Config->EMachine == EM_MIPS) + return handleNoRelaxTlsRelocation(In::MipsGot, Type, Body, C, + Offset, Addend, Expr); if ((Expr == R_TLSDESC || Expr == R_TLSDESC_PAGE || Expr == R_TLSDESC_CALL) && Config->Shared) { @@ -300,8 +299,8 @@ static bool needsPlt(RelExpr Expr) { // file (PC, or GOT for example). static bool isRelExpr(RelExpr Expr) { return Expr == R_PC || Expr == R_GOTREL || Expr == R_GOTREL_FROM_END || - Expr == R_PAGE_PC || Expr == R_RELAX_GOT_PC || Expr == R_THUNK_PC || - Expr == R_THUNK_PLT_PC; + Expr == R_MIPS_GOTREL || Expr == R_PAGE_PC || Expr == R_RELAX_GOT_PC || + Expr == R_THUNK_PC || Expr == R_THUNK_PLT_PC; } template @@ -515,11 +514,8 @@ static typename ELFT::uint computeAddend(const elf::ObjectFile &File, // For details see p. 4-19 at // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf Addend += 4; - if (Expr == R_GOTREL) { - Addend -= MipsGPOffset; - if (Body.isLocal()) - Addend += File.MipsGp0; - } + if (Expr == R_MIPS_GOTREL && Body.isLocal()) + Addend += File.MipsGp0; } if (Config->Pic && Config->EMachine == EM_PPC64 && Type == R_PPC64_TOC) Addend += getPPC64TocBase(); @@ -736,7 +732,7 @@ static void scanRelocs(InputSectionBase &C, ArrayRef Rels) { // a dynamic relocation. // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf p.4-19 if (Config->EMachine == EM_MIPS) - In::Got->addMipsEntry(Body, Addend, Expr); + In::MipsGot->addEntry(Body, Addend, Expr); continue; } @@ -771,10 +767,10 @@ static void scanRelocs(InputSectionBase &C, ArrayRef Rels) { // See "Global Offset Table" in Chapter 5 in the following document // for detailed description: // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf - In::Got->addMipsEntry(Body, Addend, Expr); + In::MipsGot->addEntry(Body, Addend, Expr); if (Body.isTls() && Body.isPreemptible()) - AddDyn({Target->TlsGotRel, In::Got, Body.getGotOffset(), - false, &Body, 0}); + AddDyn({Target->TlsGotRel, In::MipsGot, + Body.getGotOffset(), false, &Body, 0}); continue; } diff --git a/lld/ELF/Relocations.h b/lld/ELF/Relocations.h index d14b0a7..801f455 100644 --- a/lld/ELF/Relocations.h +++ b/lld/ELF/Relocations.h @@ -37,6 +37,7 @@ enum RelExpr { R_MIPS_GOT_LOCAL_PAGE, R_MIPS_GOT_OFF, R_MIPS_GOT_OFF32, + R_MIPS_GOTREL, R_MIPS_TLSGD, R_MIPS_TLSLD, R_NEG_TLS, diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index b84df2b..104e808 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -198,7 +198,7 @@ MipsOptionsSection::MipsOptionsSection() template void MipsOptionsSection::finalize() { if (!Config->Relocatable) getOptions()->getRegInfo().ri_gp_value = - In::Got->getVA() + MipsGPOffset; + In::MipsGot->getVA() + MipsGPOffset; } // MIPS .reginfo section. @@ -226,7 +226,7 @@ MipsReginfoSection::MipsReginfoSection() template void MipsReginfoSection::finalize() { if (!Config->Relocatable) - Reginfo.ri_gp_value = In::Got->getVA() + MipsGPOffset; + Reginfo.ri_gp_value = In::MipsGot->getVA() + MipsGPOffset; } static ArrayRef createInterp() { @@ -347,18 +347,70 @@ void BuildIdHexstring::writeBuildId(MutableArrayRef Buf) { template GotSection::GotSection() : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, - Target->GotEntrySize, ".got") { - if (Config->EMachine == EM_MIPS) - this->Flags |= SHF_MIPS_GPREL; -} + Target->GotEntrySize, ".got") {} template void GotSection::addEntry(SymbolBody &Sym) { Sym.GotIndex = Entries.size(); Entries.push_back(&Sym); } +template bool GotSection::addDynTlsEntry(SymbolBody &Sym) { + if (Sym.GlobalDynIndex != -1U) + return false; + Sym.GlobalDynIndex = Entries.size(); + // Global Dynamic TLS entries take two GOT slots. + Entries.push_back(nullptr); + Entries.push_back(&Sym); + return true; +} + +// Reserves TLS entries for a TLS module ID and a TLS block offset. +// In total it takes two GOT slots. +template bool GotSection::addTlsIndex() { + if (TlsIndexOff != uint32_t(-1)) + return false; + TlsIndexOff = Entries.size() * sizeof(uintX_t); + Entries.push_back(nullptr); + Entries.push_back(nullptr); + return true; +} + template -void GotSection::addMipsEntry(SymbolBody &Sym, uintX_t Addend, +typename GotSection::uintX_t +GotSection::getGlobalDynAddr(const SymbolBody &B) const { + return this->getVA() + B.GlobalDynIndex * sizeof(uintX_t); +} + +template +typename GotSection::uintX_t +GotSection::getGlobalDynOffset(const SymbolBody &B) const { + return B.GlobalDynIndex * sizeof(uintX_t); +} + +template void GotSection::finalize() { + Size = Entries.size() * sizeof(uintX_t); +} + +template void GotSection::writeTo(uint8_t *Buf) { + for (const SymbolBody *B : Entries) { + uint8_t *Entry = Buf; + Buf += sizeof(uintX_t); + if (!B) + continue; + if (B->isPreemptible()) + continue; // The dynamic linker will take care of it. + uintX_t VA = B->getVA(); + write(Entry, VA); + } +} + +template +MipsGotSection::MipsGotSection() + : SyntheticSection(SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL, + SHT_PROGBITS, Target->GotEntrySize, ".got") {} + +template +void MipsGotSection::addEntry(SymbolBody &Sym, uintX_t Addend, RelExpr Expr) { // For "true" local symbols which can be referenced from the same module // only compiler creates two instructions for address loading: @@ -427,7 +479,7 @@ void GotSection::addMipsEntry(SymbolBody &Sym, uintX_t Addend, } } -template bool GotSection::addDynTlsEntry(SymbolBody &Sym) { +template bool MipsGotSection::addDynTlsEntry(SymbolBody &Sym) { if (Sym.GlobalDynIndex != -1U) return false; Sym.GlobalDynIndex = Entries.size(); @@ -439,7 +491,7 @@ template bool GotSection::addDynTlsEntry(SymbolBody &Sym) { // Reserves TLS entries for a TLS module ID and a TLS block offset. // In total it takes two GOT slots. -template bool GotSection::addTlsIndex() { +template bool MipsGotSection::addTlsIndex() { if (TlsIndexOff != uint32_t(-1)) return false; TlsIndexOff = Entries.size() * sizeof(uintX_t); @@ -449,13 +501,13 @@ template bool GotSection::addTlsIndex() { } template -typename GotSection::uintX_t -GotSection::getMipsLocalPageOffset(uintX_t EntryValue) { +typename MipsGotSection::uintX_t +MipsGotSection::getMipsLocalPageOffset(uintX_t EntryValue) { // Initialize the entry by the %hi(EntryValue) expression // but without right-shifting. EntryValue = (EntryValue + 0x8000) & ~0xffff; // Take into account MIPS GOT header. - // See comment in the GotSection::writeTo. + // See comment in the MipsGotSection::writeTo. size_t NewIndex = MipsLocalGotPos.size() + 2; auto P = MipsLocalGotPos.insert(std::make_pair(EntryValue, NewIndex)); assert(!P.second || MipsLocalGotPos.size() <= MipsPageEntries); @@ -463,8 +515,8 @@ GotSection::getMipsLocalPageOffset(uintX_t EntryValue) { } template -typename GotSection::uintX_t -GotSection::getMipsGotOffset(const SymbolBody &B, uintX_t Addend) const { +typename MipsGotSection::uintX_t +MipsGotSection::getMipsGotOffset(const SymbolBody &B, uintX_t Addend) const { // Calculate offset of the GOT entries block: TLS, global, local. uintX_t GotBlockOff; if (B.isTls()) @@ -488,48 +540,40 @@ GotSection::getMipsGotOffset(const SymbolBody &B, uintX_t Addend) const { } template -typename GotSection::uintX_t GotSection::getMipsTlsOffset() const { +typename MipsGotSection::uintX_t MipsGotSection::getMipsTlsOffset() const { return (getMipsLocalEntriesNum() + MipsGlobal.size()) * sizeof(uintX_t); } template -typename GotSection::uintX_t -GotSection::getGlobalDynAddr(const SymbolBody &B) const { - return this->getVA() + B.GlobalDynIndex * sizeof(uintX_t); -} - -template -typename GotSection::uintX_t -GotSection::getGlobalDynOffset(const SymbolBody &B) const { +typename MipsGotSection::uintX_t +MipsGotSection::getGlobalDynOffset(const SymbolBody &B) const { return B.GlobalDynIndex * sizeof(uintX_t); } template -const SymbolBody *GotSection::getMipsFirstGlobalEntry() const { +const SymbolBody *MipsGotSection::getMipsFirstGlobalEntry() const { return MipsGlobal.empty() ? nullptr : MipsGlobal.front().first; } template -unsigned GotSection::getMipsLocalEntriesNum() const { +unsigned MipsGotSection::getMipsLocalEntriesNum() const { return MipsPageEntries + MipsLocal.size() + MipsLocal32.size(); } -template void GotSection::finalize() { +template void MipsGotSection::finalize() { size_t EntriesNum = Entries.size(); - if (Config->EMachine == EM_MIPS) { - // Take into account MIPS GOT header. - // See comment in the GotSection::writeTo. - MipsPageEntries += 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 - // page of the output section has at least one GOT relocation against it. - // Add 0x8000 to the section's size because the page address stored - // in the GOT entry is calculated as (value + 0x8000) & ~0xffff. - MipsPageEntries += (OutSec->Size + 0x8000 + 0xfffe) / 0xffff; - } - EntriesNum += getMipsLocalEntriesNum() + MipsGlobal.size(); + // Take into account MIPS GOT header. + // See comment in the MipsGotSection::writeTo. + MipsPageEntries += 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 + // page of the output section has at least one GOT relocation against it. + // Add 0x8000 to the section's size because the page address stored + // in the GOT entry is calculated as (value + 0x8000) & ~0xffff. + MipsPageEntries += (OutSec->Size + 0x8000 + 0xfffe) / 0xffff; } + EntriesNum += getMipsLocalEntriesNum() + MipsGlobal.size(); Size = EntriesNum * sizeof(uintX_t); } @@ -539,7 +583,7 @@ static void writeUint(uint8_t *Buf, typename ELFT::uint Val) { write(Buf, Val); } -template void GotSection::writeMipsGot(uint8_t *Buf) { +template void MipsGotSection::writeTo(uint8_t *Buf) { // Set the MSB of the second GOT slot. This is not required by any // MIPS ABI documentation, though. // @@ -596,23 +640,6 @@ template void GotSection::writeMipsGot(uint8_t *Buf) { } } -template void GotSection::writeTo(uint8_t *Buf) { - if (Config->EMachine == EM_MIPS) { - writeMipsGot(Buf); - return; - } - for (const SymbolBody *B : Entries) { - uint8_t *Entry = Buf; - Buf += sizeof(uintX_t); - if (!B) - continue; - if (B->isPreemptible()) - continue; // The dynamic linker will take care of it. - uintX_t VA = B->getVA(); - writeUint(Entry, VA); - } -} - template GotPltSection::GotPltSection() : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, @@ -805,12 +832,12 @@ template void DynamicSection::finalize() { Add({DT_MIPS_FLAGS, RHF_NOTPOT}); Add({DT_MIPS_BASE_ADDRESS, Config->ImageBase}); Add({DT_MIPS_SYMTABNO, Out::DynSymTab->getNumSymbols()}); - Add({DT_MIPS_LOCAL_GOTNO, In::Got->getMipsLocalEntriesNum()}); - if (const SymbolBody *B = In::Got->getMipsFirstGlobalEntry()) + Add({DT_MIPS_LOCAL_GOTNO, In::MipsGot->getMipsLocalEntriesNum()}); + if (const SymbolBody *B = In::MipsGot->getMipsFirstGlobalEntry()) Add({DT_MIPS_GOTSYM, B->DynsymIndex}); else Add({DT_MIPS_GOTSYM, Out::DynSymTab->getNumSymbols()}); - Add({DT_PLTGOT, In::Got}); + Add({DT_PLTGOT, In::MipsGot}); if (Out::MipsRldMap) Add({DT_MIPS_RLD_MAP, Out::MipsRldMap}); } @@ -902,11 +929,11 @@ template void RelocationSection::writeTo(uint8_t *Buf) { if (Config->Rela) P->r_addend = Rel.getAddend(); P->r_offset = Rel.getOffset(); - if (Config->EMachine == EM_MIPS && Rel.getInputSec() == In::Got) + if (Config->EMachine == EM_MIPS && Rel.getInputSec() == In::MipsGot) // Dynamic relocation against MIPS GOT section make deal TLS entries // allocated in the end of the GOT. We need to adjust the offset to take // in account 'local' and 'global' GOT entries. - P->r_offset += In::Got->getMipsTlsOffset(); + P->r_offset += In::MipsGot->getMipsTlsOffset(); P->setSymbolAndType(Rel.getSymIndex(), Rel.Type, Config->Mips64EL); } @@ -999,6 +1026,11 @@ template class elf::GotSection; template class elf::GotSection; template class elf::GotSection; +template class elf::MipsGotSection; +template class elf::MipsGotSection; +template class elf::MipsGotSection; +template class elf::MipsGotSection; + template class elf::GotPltSection; template class elf::GotPltSection; template class elf::GotPltSection; diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index f420f9b..0a3774e 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -147,13 +147,39 @@ public: size_t getSize() const override { return Size; } void finalize() override; void addEntry(SymbolBody &Sym); - void addMipsEntry(SymbolBody &Sym, uintX_t Addend, RelExpr Expr); + bool addDynTlsEntry(SymbolBody &Sym); + bool addTlsIndex(); + bool empty() const { return Entries.empty(); } + uintX_t getGlobalDynAddr(const SymbolBody &B) const; + uintX_t getGlobalDynOffset(const SymbolBody &B) const; + + uintX_t getTlsIndexVA() { return this->getVA() + TlsIndexOff; } + uint32_t getTlsIndexOff() const { return TlsIndexOff; } + + // Flag to force GOT to be in output if we have relocations + // that relies on its address. + bool HasGotOffRel = false; + +private: + std::vector Entries; + uint32_t TlsIndexOff = -1; + uintX_t Size = 0; +}; + +template class MipsGotSection final : public SyntheticSection { + typedef typename ELFT::uint uintX_t; + +public: + MipsGotSection(); + void writeTo(uint8_t *Buf) override; + size_t getSize() const override { return Size; } + void finalize() override; + void addEntry(SymbolBody &Sym, uintX_t Addend, RelExpr Expr); bool addDynTlsEntry(SymbolBody &Sym); bool addTlsIndex(); bool empty() const { return MipsPageEntries == 0 && Entries.empty(); } uintX_t getMipsLocalPageOffset(uintX_t Addr); uintX_t getMipsGotOffset(const SymbolBody &B, uintX_t Addend) const; - uintX_t getGlobalDynAddr(const SymbolBody &B) const; uintX_t getGlobalDynOffset(const SymbolBody &B) const; // Returns the symbol which corresponds to the first entry of the global part @@ -170,13 +196,8 @@ public: // after 'local' and 'global' entries. uintX_t getMipsTlsOffset() const; - uintX_t getTlsIndexVA() { return this->getVA() + TlsIndexOff; } uint32_t getTlsIndexOff() const { return TlsIndexOff; } - // Flag to force GOT to be in output if we have relocations - // that relies on its address. - bool HasGotOffRel = false; - private: std::vector Entries; uint32_t TlsIndexOff = -1; @@ -199,9 +220,6 @@ private: MipsGotEntries MipsLocal; MipsGotEntries MipsLocal32; MipsGotEntries MipsGlobal; - - // Write MIPS-specific parts of the GOT. - void writeMipsGot(uint8_t *Buf); }; template @@ -353,6 +371,7 @@ template struct In { static DynamicSection *Dynamic; static StringTableSection *DynStrTab; static GotSection *Got; + static MipsGotSection *MipsGot; static GotPltSection *GotPlt; static InputSection *Interp; static MipsAbiFlagsSection *MipsAbiFlags; @@ -369,6 +388,7 @@ template InputSection *In::Common; template DynamicSection *In::Dynamic; template StringTableSection *In::DynStrTab; template GotSection *In::Got; +template MipsGotSection *In::MipsGot; template GotPltSection *In::GotPlt; template InputSection *In::Interp; template MipsAbiFlagsSection *In::MipsAbiFlags; diff --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp index 447490c..3ad2316 100644 --- a/lld/ELF/Target.cpp +++ b/lld/ELF/Target.cpp @@ -1933,7 +1933,7 @@ RelExpr MipsTargetInfo::getRelExpr(uint32_t Type, return R_HINT; case R_MIPS_GPREL16: case R_MIPS_GPREL32: - return R_GOTREL; + return R_MIPS_GOTREL; case R_MIPS_26: return R_PLT; case R_MIPS_HI16: diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 9b749c7..2fecbc0 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -312,7 +312,11 @@ template void Writer::createSyntheticSections() { } } - In::Got = make>(); + if (Config->EMachine == EM_MIPS) + In::MipsGot = make>(); + else + In::Got = make>(); + In::GotPlt = make>(); } @@ -427,7 +431,11 @@ template bool elf::isRelroSection(const OutputSectionBase *Sec) { return true; if (Sec == In::GotPlt->OutSec) return Config->ZNow; - if (Sec == In::Dynamic->OutSec || Sec == In::Got->OutSec) + if (Sec == In::Dynamic->OutSec) + return true; + if (In::Got && Sec == In::Got->OutSec) + return true; + if (In::MipsGot && Sec == In::MipsGot->OutSec) return true; StringRef S = Sec->getName(); return S == ".data.rel.ro" || S == ".ctors" || S == ".dtors" || S == ".jcr" || @@ -603,11 +611,12 @@ template void Writer::addReservedSymbols() { // so that it points to an absolute address which is relative to GOT. // See "Global Data Symbols" in Chapter 6 in the following document: // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf - addRegular("_gp", In::Got, MipsGPOffset); + addRegular("_gp", In::MipsGot, MipsGPOffset); // On MIPS O32 ABI, _gp_disp is a magic symbol designates offset between // start of function and 'gp' pointer into GOT. - Symbol *Sym = addOptionalRegular("_gp_disp", In::Got, MipsGPOffset); + Symbol *Sym = + addOptionalRegular("_gp_disp", In::MipsGot, MipsGPOffset); if (Sym) ElfSym::MipsGpDisp = Sym->body(); @@ -615,7 +624,7 @@ template void Writer::addReservedSymbols() { // pointer. This symbol is used in the code generated by .cpload pseudo-op // in case of using -mno-shared option. // https://sourceware.org/ml/binutils/2004-12/msg00094.html - addOptionalRegular("__gnu_local_gp", In::Got, MipsGPOffset); + addOptionalRegular("__gnu_local_gp", In::MipsGot, MipsGPOffset); } // In the assembly for 32 bit x86 the _GLOBAL_OFFSET_TABLE_ symbol @@ -945,10 +954,10 @@ template void Writer::finalizeSections() { Sec->finalize(); // Dynamic section must be the last one in this list. - finalizeSynthetic({In::ShStrTab, In::StrTab, - In::DynStrTab, In::Got, In::GotPlt, - In::RelaDyn, In::RelaPlt, - In::Dynamic}); + finalizeSynthetic( + {In::ShStrTab, In::StrTab, In::DynStrTab, In::Got, + In::MipsGot, In::GotPlt, In::RelaDyn, + In::RelaPlt, In::Dynamic}); // Now that all output offsets are fixed. Finalize mergeable sections // to fix their maps from input offsets to output offsets. @@ -957,12 +966,12 @@ template void Writer::finalizeSections() { } template bool Writer::needsGot() { - if (!In::Got->empty()) - return true; - // We add the .got section to the result for dynamic MIPS target because // its address and properties are mentioned in the .dynamic section. - if (Config->EMachine == EM_MIPS && !Config->Relocatable) + if (Config->EMachine == EM_MIPS) + return !Config->Relocatable; + + if (!In::Got->empty()) return true; // If we have a relocation that is relative to GOT (such as GOTOFFREL), @@ -1010,8 +1019,12 @@ template void Writer::addPredefinedSections() { // We fill .got and .got.plt sections in scanRelocs(). This is the // reason we don't add it earlier in createSections(). - if (needsGot()) - addInputSec(In::Got); + if (needsGot()) { + if (Config->EMachine == EM_MIPS) + addInputSec(In::MipsGot); + else + addInputSec(In::Got); + } if (!In::GotPlt->empty()) addInputSec(In::GotPlt);