diff options
| -rw-r--r-- | lld/ELF/InputSection.cpp | 14 | ||||
| -rw-r--r-- | lld/ELF/Relocations.cpp | 54 | ||||
| -rw-r--r-- | lld/ELF/Relocations.h | 1 | ||||
| -rw-r--r-- | lld/ELF/SyntheticSections.cpp | 156 | ||||
| -rw-r--r-- | lld/ELF/SyntheticSections.h | 40 | ||||
| -rw-r--r-- | lld/ELF/Target.cpp | 2 | ||||
| -rw-r--r-- | lld/ELF/Writer.cpp | 43 |
7 files changed, 187 insertions, 123 deletions
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 28e1d71402d..7cec93d75e4 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<ELFT>::Got->getMipsLocalPageOffset(Body.getVA<ELFT>(A)); + return In<ELFT>::MipsGot->getMipsLocalPageOffset(Body.getVA<ELFT>(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<ELFT>::Got->getMipsGotOffset(Body, A); + return In<ELFT>::MipsGot->getMipsGotOffset(Body, A); + case R_MIPS_GOTREL: + return Body.getVA<ELFT>(A) - In<ELFT>::MipsGot->getVA() - MipsGPOffset; case R_MIPS_TLSGD: - return In<ELFT>::Got->getGlobalDynOffset(Body) + - In<ELFT>::Got->getMipsTlsOffset() - MipsGPOffset; + return In<ELFT>::MipsGot->getGlobalDynOffset(Body) + + In<ELFT>::MipsGot->getMipsTlsOffset() - MipsGPOffset; case R_MIPS_TLSLD: - return In<ELFT>::Got->getTlsIndexOff() + In<ELFT>::Got->getMipsTlsOffset() - - MipsGPOffset; + return In<ELFT>::MipsGot->getTlsIndexOff() + + In<ELFT>::MipsGot->getMipsTlsOffset() - MipsGPOffset; case R_PPC_OPD: { uint64_t SymVA = Body.getVA<ELFT>(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 f68c9cf5add..c402bce8e13 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 <class ELFT> -static unsigned handleNoRelaxTlsRelocation(uint32_t Type, SymbolBody &Body, - InputSectionBase<ELFT> &C, - typename ELFT::uint Offset, - typename ELFT::uint Addend, - RelExpr Expr) { +template <class ELFT, class GOT> +static unsigned handleNoRelaxTlsRelocation( + GOT *Got, uint32_t Type, SymbolBody &Body, InputSectionBase<ELFT> &C, + typename ELFT::uint Offset, typename ELFT::uint Addend, RelExpr Expr) { if (Expr == R_MIPS_TLSLD || Expr == R_TLSLD_PC) { - if (In<ELFT>::Got->addTlsIndex() && - (Config->Pic || Config->EMachine == EM_ARM)) - In<ELFT>::RelaDyn->addReloc({Target->TlsModuleIndexRel, In<ELFT>::Got, - In<ELFT>::Got->getTlsIndexOff(), false, - nullptr, 0}); + if (Got->addTlsIndex() && (Config->Pic || Config->EMachine == EM_ARM)) + In<ELFT>::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<ELFT>::Got->addDynTlsEntry(Body) && + if (Got->addDynTlsEntry(Body) && (Body.isPreemptible() || Config->EMachine == EM_ARM)) { - uintX_t Off = In<ELFT>::Got->getGlobalDynOffset(Body); + uintX_t Off = Got->getGlobalDynOffset(Body); In<ELFT>::RelaDyn->addReloc( - {Target->TlsModuleIndexRel, In<ELFT>::Got, Off, false, &Body, 0}); + {Target->TlsModuleIndexRel, Got, Off, false, &Body, 0}); if (Body.isPreemptible()) - In<ELFT>::RelaDyn->addReloc({Target->TlsOffsetRel, In<ELFT>::Got, + In<ELFT>::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<ELFT>(Type, Body, C, Offset, Addend, - Expr); + if (Config->EMachine == EM_ARM) + return handleNoRelaxTlsRelocation<ELFT>(In<ELFT>::Got, Type, Body, C, + Offset, Addend, Expr); + if (Config->EMachine == EM_MIPS) + return handleNoRelaxTlsRelocation<ELFT>(In<ELFT>::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 <class ELFT> @@ -515,11 +514,8 @@ static typename ELFT::uint computeAddend(const elf::ObjectFile<ELFT> &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<ELFT> &C, ArrayRef<RelTy> 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<ELFT>::Got->addMipsEntry(Body, Addend, Expr); + In<ELFT>::MipsGot->addEntry(Body, Addend, Expr); continue; } @@ -771,10 +767,10 @@ static void scanRelocs(InputSectionBase<ELFT> &C, ArrayRef<RelTy> 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<ELFT>::Got->addMipsEntry(Body, Addend, Expr); + In<ELFT>::MipsGot->addEntry(Body, Addend, Expr); if (Body.isTls() && Body.isPreemptible()) - AddDyn({Target->TlsGotRel, In<ELFT>::Got, Body.getGotOffset<ELFT>(), - false, &Body, 0}); + AddDyn({Target->TlsGotRel, In<ELFT>::MipsGot, + Body.getGotOffset<ELFT>(), false, &Body, 0}); continue; } diff --git a/lld/ELF/Relocations.h b/lld/ELF/Relocations.h index d14b0a7ad95..801f4555422 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 b84df2b30df..104e808c9a7 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -198,7 +198,7 @@ MipsOptionsSection<ELFT>::MipsOptionsSection() template <class ELFT> void MipsOptionsSection<ELFT>::finalize() { if (!Config->Relocatable) getOptions()->getRegInfo().ri_gp_value = - In<ELFT>::Got->getVA() + MipsGPOffset; + In<ELFT>::MipsGot->getVA() + MipsGPOffset; } // MIPS .reginfo section. @@ -226,7 +226,7 @@ MipsReginfoSection<ELFT>::MipsReginfoSection() template <class ELFT> void MipsReginfoSection<ELFT>::finalize() { if (!Config->Relocatable) - Reginfo.ri_gp_value = In<ELFT>::Got->getVA() + MipsGPOffset; + Reginfo.ri_gp_value = In<ELFT>::MipsGot->getVA() + MipsGPOffset; } static ArrayRef<uint8_t> createInterp() { @@ -347,18 +347,70 @@ void BuildIdHexstring<ELFT>::writeBuildId(MutableArrayRef<uint8_t> Buf) { template <class ELFT> GotSection<ELFT>::GotSection() : SyntheticSection<ELFT>(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, - Target->GotEntrySize, ".got") { - if (Config->EMachine == EM_MIPS) - this->Flags |= SHF_MIPS_GPREL; -} + Target->GotEntrySize, ".got") {} template <class ELFT> void GotSection<ELFT>::addEntry(SymbolBody &Sym) { Sym.GotIndex = Entries.size(); Entries.push_back(&Sym); } +template <class ELFT> bool GotSection<ELFT>::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 <class ELFT> bool GotSection<ELFT>::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 <class ELFT> -void GotSection<ELFT>::addMipsEntry(SymbolBody &Sym, uintX_t Addend, +typename GotSection<ELFT>::uintX_t +GotSection<ELFT>::getGlobalDynAddr(const SymbolBody &B) const { + return this->getVA() + B.GlobalDynIndex * sizeof(uintX_t); +} + +template <class ELFT> +typename GotSection<ELFT>::uintX_t +GotSection<ELFT>::getGlobalDynOffset(const SymbolBody &B) const { + return B.GlobalDynIndex * sizeof(uintX_t); +} + +template <class ELFT> void GotSection<ELFT>::finalize() { + Size = Entries.size() * sizeof(uintX_t); +} + +template <class ELFT> void GotSection<ELFT>::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<ELFT>(); + write<uintX_t, ELFT::TargetEndianness, sizeof(uintX_t)>(Entry, VA); + } +} + +template <class ELFT> +MipsGotSection<ELFT>::MipsGotSection() + : SyntheticSection<ELFT>(SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL, + SHT_PROGBITS, Target->GotEntrySize, ".got") {} + +template <class ELFT> +void MipsGotSection<ELFT>::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<ELFT>::addMipsEntry(SymbolBody &Sym, uintX_t Addend, } } -template <class ELFT> bool GotSection<ELFT>::addDynTlsEntry(SymbolBody &Sym) { +template <class ELFT> bool MipsGotSection<ELFT>::addDynTlsEntry(SymbolBody &Sym) { if (Sym.GlobalDynIndex != -1U) return false; Sym.GlobalDynIndex = Entries.size(); @@ -439,7 +491,7 @@ template <class ELFT> bool GotSection<ELFT>::addDynTlsEntry(SymbolBody &Sym) { // Reserves TLS entries for a TLS module ID and a TLS block offset. // In total it takes two GOT slots. -template <class ELFT> bool GotSection<ELFT>::addTlsIndex() { +template <class ELFT> bool MipsGotSection<ELFT>::addTlsIndex() { if (TlsIndexOff != uint32_t(-1)) return false; TlsIndexOff = Entries.size() * sizeof(uintX_t); @@ -449,13 +501,13 @@ template <class ELFT> bool GotSection<ELFT>::addTlsIndex() { } template <class ELFT> -typename GotSection<ELFT>::uintX_t -GotSection<ELFT>::getMipsLocalPageOffset(uintX_t EntryValue) { +typename MipsGotSection<ELFT>::uintX_t +MipsGotSection<ELFT>::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<ELFT>::getMipsLocalPageOffset(uintX_t EntryValue) { } template <class ELFT> -typename GotSection<ELFT>::uintX_t -GotSection<ELFT>::getMipsGotOffset(const SymbolBody &B, uintX_t Addend) const { +typename MipsGotSection<ELFT>::uintX_t +MipsGotSection<ELFT>::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<ELFT>::getMipsGotOffset(const SymbolBody &B, uintX_t Addend) const { } template <class ELFT> -typename GotSection<ELFT>::uintX_t GotSection<ELFT>::getMipsTlsOffset() const { +typename MipsGotSection<ELFT>::uintX_t MipsGotSection<ELFT>::getMipsTlsOffset() const { return (getMipsLocalEntriesNum() + MipsGlobal.size()) * sizeof(uintX_t); } template <class ELFT> -typename GotSection<ELFT>::uintX_t -GotSection<ELFT>::getGlobalDynAddr(const SymbolBody &B) const { - return this->getVA() + B.GlobalDynIndex * sizeof(uintX_t); -} - -template <class ELFT> -typename GotSection<ELFT>::uintX_t -GotSection<ELFT>::getGlobalDynOffset(const SymbolBody &B) const { +typename MipsGotSection<ELFT>::uintX_t +MipsGotSection<ELFT>::getGlobalDynOffset(const SymbolBody &B) const { return B.GlobalDynIndex * sizeof(uintX_t); } template <class ELFT> -const SymbolBody *GotSection<ELFT>::getMipsFirstGlobalEntry() const { +const SymbolBody *MipsGotSection<ELFT>::getMipsFirstGlobalEntry() const { return MipsGlobal.empty() ? nullptr : MipsGlobal.front().first; } template <class ELFT> -unsigned GotSection<ELFT>::getMipsLocalEntriesNum() const { +unsigned MipsGotSection<ELFT>::getMipsLocalEntriesNum() const { return MipsPageEntries + MipsLocal.size() + MipsLocal32.size(); } -template <class ELFT> void GotSection<ELFT>::finalize() { +template <class ELFT> void MipsGotSection<ELFT>::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<uintX_t, ELFT::TargetEndianness, sizeof(uintX_t)>(Buf, Val); } -template <class ELFT> void GotSection<ELFT>::writeMipsGot(uint8_t *Buf) { +template <class ELFT> void MipsGotSection<ELFT>::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 <class ELFT> void GotSection<ELFT>::writeMipsGot(uint8_t *Buf) { } } -template <class ELFT> void GotSection<ELFT>::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<ELFT>(); - writeUint<ELFT>(Entry, VA); - } -} - template <class ELFT> GotPltSection<ELFT>::GotPltSection() : SyntheticSection<ELFT>(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, @@ -805,12 +832,12 @@ template <class ELFT> void DynamicSection<ELFT>::finalize() { Add({DT_MIPS_FLAGS, RHF_NOTPOT}); Add({DT_MIPS_BASE_ADDRESS, Config->ImageBase}); Add({DT_MIPS_SYMTABNO, Out<ELFT>::DynSymTab->getNumSymbols()}); - Add({DT_MIPS_LOCAL_GOTNO, In<ELFT>::Got->getMipsLocalEntriesNum()}); - if (const SymbolBody *B = In<ELFT>::Got->getMipsFirstGlobalEntry()) + Add({DT_MIPS_LOCAL_GOTNO, In<ELFT>::MipsGot->getMipsLocalEntriesNum()}); + if (const SymbolBody *B = In<ELFT>::MipsGot->getMipsFirstGlobalEntry()) Add({DT_MIPS_GOTSYM, B->DynsymIndex}); else Add({DT_MIPS_GOTSYM, Out<ELFT>::DynSymTab->getNumSymbols()}); - Add({DT_PLTGOT, In<ELFT>::Got}); + Add({DT_PLTGOT, In<ELFT>::MipsGot}); if (Out<ELFT>::MipsRldMap) Add({DT_MIPS_RLD_MAP, Out<ELFT>::MipsRldMap}); } @@ -902,11 +929,11 @@ template <class ELFT> void RelocationSection<ELFT>::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<ELFT>::Got) + if (Config->EMachine == EM_MIPS && Rel.getInputSec() == In<ELFT>::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<ELFT>::Got->getMipsTlsOffset(); + P->r_offset += In<ELFT>::MipsGot->getMipsTlsOffset(); P->setSymbolAndType(Rel.getSymIndex(), Rel.Type, Config->Mips64EL); } @@ -999,6 +1026,11 @@ template class elf::GotSection<ELF32BE>; template class elf::GotSection<ELF64LE>; template class elf::GotSection<ELF64BE>; +template class elf::MipsGotSection<ELF32LE>; +template class elf::MipsGotSection<ELF32BE>; +template class elf::MipsGotSection<ELF64LE>; +template class elf::MipsGotSection<ELF64BE>; + template class elf::GotPltSection<ELF32LE>; template class elf::GotPltSection<ELF32BE>; template class elf::GotPltSection<ELF64LE>; diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index f420f9bf460..0a3774e61f9 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<const SymbolBody *> Entries; + uint32_t TlsIndexOff = -1; + uintX_t Size = 0; +}; + +template <class ELFT> class MipsGotSection final : public SyntheticSection<ELFT> { + 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<const SymbolBody *> 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 <class ELFT> @@ -353,6 +371,7 @@ template <class ELFT> struct In { static DynamicSection<ELFT> *Dynamic; static StringTableSection<ELFT> *DynStrTab; static GotSection<ELFT> *Got; + static MipsGotSection<ELFT> *MipsGot; static GotPltSection<ELFT> *GotPlt; static InputSection<ELFT> *Interp; static MipsAbiFlagsSection<ELFT> *MipsAbiFlags; @@ -369,6 +388,7 @@ template <class ELFT> InputSection<ELFT> *In<ELFT>::Common; template <class ELFT> DynamicSection<ELFT> *In<ELFT>::Dynamic; template <class ELFT> StringTableSection<ELFT> *In<ELFT>::DynStrTab; template <class ELFT> GotSection<ELFT> *In<ELFT>::Got; +template <class ELFT> MipsGotSection<ELFT> *In<ELFT>::MipsGot; template <class ELFT> GotPltSection<ELFT> *In<ELFT>::GotPlt; template <class ELFT> InputSection<ELFT> *In<ELFT>::Interp; template <class ELFT> MipsAbiFlagsSection<ELFT> *In<ELFT>::MipsAbiFlags; diff --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp index 447490ceece..3ad23165534 100644 --- a/lld/ELF/Target.cpp +++ b/lld/ELF/Target.cpp @@ -1933,7 +1933,7 @@ RelExpr MipsTargetInfo<ELFT>::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 9b749c7cd0a..2fecbc0cb00 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -312,7 +312,11 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() { } } - In<ELFT>::Got = make<GotSection<ELFT>>(); + if (Config->EMachine == EM_MIPS) + In<ELFT>::MipsGot = make<MipsGotSection<ELFT>>(); + else + In<ELFT>::Got = make<GotSection<ELFT>>(); + In<ELFT>::GotPlt = make<GotPltSection<ELFT>>(); } @@ -427,7 +431,11 @@ template <class ELFT> bool elf::isRelroSection(const OutputSectionBase *Sec) { return true; if (Sec == In<ELFT>::GotPlt->OutSec) return Config->ZNow; - if (Sec == In<ELFT>::Dynamic->OutSec || Sec == In<ELFT>::Got->OutSec) + if (Sec == In<ELFT>::Dynamic->OutSec) + return true; + if (In<ELFT>::Got && Sec == In<ELFT>::Got->OutSec) + return true; + if (In<ELFT>::MipsGot && Sec == In<ELFT>::MipsGot->OutSec) return true; StringRef S = Sec->getName(); return S == ".data.rel.ro" || S == ".ctors" || S == ".dtors" || S == ".jcr" || @@ -603,11 +611,12 @@ template <class ELFT> void Writer<ELFT>::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<ELFT>::Got, MipsGPOffset); + addRegular("_gp", In<ELFT>::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<ELFT>::Got, MipsGPOffset); + Symbol *Sym = + addOptionalRegular("_gp_disp", In<ELFT>::MipsGot, MipsGPOffset); if (Sym) ElfSym<ELFT>::MipsGpDisp = Sym->body(); @@ -615,7 +624,7 @@ template <class ELFT> void Writer<ELFT>::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<ELFT>::Got, MipsGPOffset); + addOptionalRegular("__gnu_local_gp", In<ELFT>::MipsGot, MipsGPOffset); } // In the assembly for 32 bit x86 the _GLOBAL_OFFSET_TABLE_ symbol @@ -945,10 +954,10 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { Sec->finalize(); // Dynamic section must be the last one in this list. - finalizeSynthetic<ELFT>({In<ELFT>::ShStrTab, In<ELFT>::StrTab, - In<ELFT>::DynStrTab, In<ELFT>::Got, In<ELFT>::GotPlt, - In<ELFT>::RelaDyn, In<ELFT>::RelaPlt, - In<ELFT>::Dynamic}); + finalizeSynthetic<ELFT>( + {In<ELFT>::ShStrTab, In<ELFT>::StrTab, In<ELFT>::DynStrTab, In<ELFT>::Got, + In<ELFT>::MipsGot, In<ELFT>::GotPlt, In<ELFT>::RelaDyn, + In<ELFT>::RelaPlt, In<ELFT>::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 <class ELFT> void Writer<ELFT>::finalizeSections() { } template <class ELFT> bool Writer<ELFT>::needsGot() { - if (!In<ELFT>::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<ELFT>::Got->empty()) return true; // If we have a relocation that is relative to GOT (such as GOTOFFREL), @@ -1010,8 +1019,12 @@ template <class ELFT> void Writer<ELFT>::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<ELFT>::Got); + if (needsGot()) { + if (Config->EMachine == EM_MIPS) + addInputSec(In<ELFT>::MipsGot); + else + addInputSec(In<ELFT>::Got); + } if (!In<ELFT>::GotPlt->empty()) addInputSec(In<ELFT>::GotPlt); |

