[lld] r287150 - [ELF][MIPS] Add MipsGotSection to handle MIPS GOT

Simon Atanasyan via llvm-commits llvm-commits at lists.llvm.org
Wed Nov 16 13:01:02 PST 2016


Author: atanasyan
Date: Wed Nov 16 15:01:02 2016
New Revision: 287150

URL: http://llvm.org/viewvc/llvm-project?rev=287150&view=rev
Log:
[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

Modified:
    lld/trunk/ELF/InputSection.cpp
    lld/trunk/ELF/Relocations.cpp
    lld/trunk/ELF/Relocations.h
    lld/trunk/ELF/SyntheticSections.cpp
    lld/trunk/ELF/SyntheticSections.h
    lld/trunk/ELF/Target.cpp
    lld/trunk/ELF/Writer.cpp

Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=287150&r1=287149&r2=287150&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Wed Nov 16 15:01:02 2016
@@ -382,19 +382,21 @@ static typename ELFT::uint getSymVA(uint
     // 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

Modified: lld/trunk/ELF/Relocations.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.cpp?rev=287150&r1=287149&r2=287150&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.cpp (original)
+++ lld/trunk/ELF/Relocations.cpp Wed Nov 16 15:01:02 2016
@@ -94,30 +94,26 @@ static bool isPreemptible(const SymbolBo
 // 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(uint
 
   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
       // 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<
       // 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<
         // 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;
       }
 

Modified: lld/trunk/ELF/Relocations.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.h?rev=287150&r1=287149&r2=287150&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.h (original)
+++ lld/trunk/ELF/Relocations.h Wed Nov 16 15:01:02 2016
@@ -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,

Modified: lld/trunk/ELF/SyntheticSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.cpp?rev=287150&r1=287149&r2=287150&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.cpp (original)
+++ lld/trunk/ELF/SyntheticSections.cpp Wed Nov 16 15:01:02 2016
@@ -198,7 +198,7 @@ MipsOptionsSection<ELFT>::MipsOptionsSec
 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>::MipsReginfoSec
 
 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>::writeBuildI
 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(Symb
   }
 }
 
-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<EL
 
 // 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<EL
 }
 
 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
 }
 
 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
 }
 
 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, type
   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<EL
   }
 }
 
-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 DynamicSectio
     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 RelocationSec
     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>;

Modified: lld/trunk/ELF/SyntheticSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.h?rev=287150&r1=287149&r2=287150&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.h (original)
+++ lld/trunk/ELF/SyntheticSections.h Wed Nov 16 15:01:02 2016
@@ -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>
 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;

Modified: lld/trunk/ELF/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.cpp?rev=287150&r1=287149&r2=287150&view=diff
==============================================================================
--- lld/trunk/ELF/Target.cpp (original)
+++ lld/trunk/ELF/Target.cpp Wed Nov 16 15:01:02 2016
@@ -1933,7 +1933,7 @@ RelExpr MipsTargetInfo<ELFT>::getRelExpr
     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:

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=287150&r1=287149&r2=287150&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Wed Nov 16 15:01:02 2016
@@ -312,7 +312,11 @@ template <class ELFT> void Writer<ELFT>:
     }
   }
 
-  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::isRelroS
     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>:
     // 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>:
     // 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>:
     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>:
 }
 
 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>:
 
   // 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);




More information about the llvm-commits mailing list