Index: lld/trunk/ELF/InputSection.cpp =================================================================== --- lld/trunk/ELF/InputSection.cpp +++ lld/trunk/ELF/InputSection.cpp @@ -382,19 +382,21 @@ // 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 Index: lld/trunk/ELF/Relocations.h =================================================================== --- lld/trunk/ELF/Relocations.h +++ lld/trunk/ELF/Relocations.h @@ -37,6 +37,7 @@ 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, Index: lld/trunk/ELF/Relocations.cpp =================================================================== --- lld/trunk/ELF/Relocations.cpp +++ lld/trunk/ELF/Relocations.cpp @@ -94,30 +94,26 @@ // 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 @@ 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 @@ // 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 @@ // 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 @@ // 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 @@ // 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; } Index: lld/trunk/ELF/SyntheticSections.h =================================================================== --- lld/trunk/ELF/SyntheticSections.h +++ lld/trunk/ELF/SyntheticSections.h @@ -147,13 +147,39 @@ 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 @@ // 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 @@ MipsGotEntries MipsLocal; MipsGotEntries MipsLocal32; MipsGotEntries MipsGlobal; - - // Write MIPS-specific parts of the GOT. - void writeMipsGot(uint8_t *Buf); }; template @@ -353,6 +371,7 @@ 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 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; Index: lld/trunk/ELF/SyntheticSections.cpp =================================================================== --- lld/trunk/ELF/SyntheticSections.cpp +++ lld/trunk/ELF/SyntheticSections.cpp @@ -198,7 +198,7 @@ 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 @@ 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 @@ 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 @@ } } -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 @@ // 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 -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 @@ } 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 @@ } 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 @@ 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::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 @@ 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 @@ 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::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; Index: lld/trunk/ELF/Target.cpp =================================================================== --- lld/trunk/ELF/Target.cpp +++ lld/trunk/ELF/Target.cpp @@ -1933,7 +1933,7 @@ 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: Index: lld/trunk/ELF/Writer.cpp =================================================================== --- lld/trunk/ELF/Writer.cpp +++ lld/trunk/ELF/Writer.cpp @@ -312,7 +312,11 @@ } } - In::Got = make>(); + if (Config->EMachine == EM_MIPS) + In::MipsGot = make>(); + else + In::Got = make>(); + In::GotPlt = make>(); } @@ -427,7 +431,11 @@ 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 @@ // 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 @@ // 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 @@ 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 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 @@ // 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);