[lld] r286397 - [ELF][MIPS] Convert .reginfo and .MIPS.options sections to synthetic input sections

Simon Atanasyan via llvm-commits llvm-commits at lists.llvm.org
Wed Nov 9 13:36:56 PST 2016


Author: atanasyan
Date: Wed Nov  9 15:36:56 2016
New Revision: 286397

URL: http://llvm.org/viewvc/llvm-project?rev=286397&view=rev
Log:
[ELF][MIPS] Convert .reginfo and .MIPS.options sections to synthetic input sections

Previously, we have both input and output sections for .reginfo and
.MIPS.options. Now for each such sections we have one synthetic input
sections: MipsReginfoSection and MipsOptionsSection respectively.

Both sections are handled as regular sections until the control reaches
Writer. Writer then aggregates all sections whose type is SHT_MIPS_REGINFO
or SHT_MIPS_OPTIONS to create a single synthesized input section. In that
moment Writer also save GP0 value to the MipsGp0 field of the corresponding
ObjectFile. This value required for R_MIPS_GPREL16 and R_MIPS_GPREL32
relocations calculation.

Differential revision: https://reviews.llvm.org/D26444

Removed:
    lld/trunk/test/ELF/invalid/mips-multiple-options.test
    lld/trunk/test/ELF/invalid/mips-multiple-reginfo.test
Modified:
    lld/trunk/ELF/InputFiles.cpp
    lld/trunk/ELF/InputFiles.h
    lld/trunk/ELF/InputSection.cpp
    lld/trunk/ELF/InputSection.h
    lld/trunk/ELF/OutputSections.cpp
    lld/trunk/ELF/OutputSections.h
    lld/trunk/ELF/Relocations.cpp
    lld/trunk/ELF/SyntheticSections.cpp
    lld/trunk/ELF/SyntheticSections.h
    lld/trunk/ELF/Writer.cpp
    lld/trunk/test/ELF/basic-mips.s
    lld/trunk/test/ELF/invalid/mips-invalid-options-descriptor.s
    lld/trunk/test/ELF/mips-gprel32-relocs-gp0.s
    lld/trunk/test/ELF/mips-n32-rels.s
    lld/trunk/test/ELF/mips-options-r.test

Modified: lld/trunk/ELF/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.cpp?rev=286397&r1=286396&r2=286397&view=diff
==============================================================================
--- lld/trunk/ELF/InputFiles.cpp (original)
+++ lld/trunk/ELF/InputFiles.cpp Wed Nov  9 15:36:56 2016
@@ -160,14 +160,6 @@ ArrayRef<SymbolBody *> elf::ObjectFile<E
   return makeArrayRef(this->SymbolBodies).slice(1);
 }
 
-template <class ELFT> uint32_t elf::ObjectFile<ELFT>::getMipsGp0() const {
-  if (ELFT::Is64Bits && MipsOptions && MipsOptions->Reginfo)
-    return MipsOptions->Reginfo->ri_gp_value;
-  if (!ELFT::Is64Bits && MipsReginfo && MipsReginfo->Reginfo)
-    return MipsReginfo->Reginfo->ri_gp_value;
-  return 0;
-}
-
 template <class ELFT>
 void elf::ObjectFile<ELFT>::parse(DenseSet<CachedHashStringRef> &ComdatGroups) {
   // Read section and symbol tables.
@@ -348,18 +340,6 @@ elf::ObjectFile<ELFT>::createInputSectio
     // FIXME: ARM meta-data section. At present attributes are ignored,
     // they can be used to reason about object compatibility.
     return &InputSection<ELFT>::Discarded;
-  case SHT_MIPS_REGINFO:
-    if (MipsReginfo)
-      fatal(getFilename(this) +
-            ": multiple SHT_MIPS_REGINFO sections are not allowed");
-    MipsReginfo.reset(new MipsReginfoInputSection<ELFT>(this, &Sec, Name));
-    return MipsReginfo.get();
-  case SHT_MIPS_OPTIONS:
-    if (MipsOptions)
-      fatal(getFilename(this) +
-            ": multiple SHT_MIPS_OPTIONS sections are not allowed");
-    MipsOptions.reset(new MipsOptionsInputSection<ELFT>(this, &Sec, Name));
-    return MipsOptions.get();
   case SHT_MIPS_ABIFLAGS:
     if (MipsAbiFlags)
       fatal(getFilename(this) +

Modified: lld/trunk/ELF/InputFiles.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.h?rev=286397&r1=286396&r2=286397&view=diff
==============================================================================
--- lld/trunk/ELF/InputFiles.h (original)
+++ lld/trunk/ELF/InputFiles.h Wed Nov  9 15:36:56 2016
@@ -162,10 +162,10 @@ public:
   // If no information is available, returns "".
   std::string getLineInfo(InputSectionBase<ELFT> *S, uintX_t Offset);
 
-  // Get MIPS GP0 value defined by this file. This value represents the gp value
+  // MIPS GP0 value defined by this file. This value represents the gp value
   // used to create the relocatable object and required to support
   // R_MIPS_GPREL16 / R_MIPS_GPREL32 relocations.
-  uint32_t getMipsGp0() const;
+  uint32_t MipsGp0 = 0;
 
   // The number is the offset in the string table. It will be used as the
   // st_name of the symbol.
@@ -194,10 +194,6 @@ private:
   // List of all symbols referenced or defined by this file.
   std::vector<SymbolBody *> SymbolBodies;
 
-  // MIPS .reginfo section defined by this file.
-  std::unique_ptr<MipsReginfoInputSection<ELFT>> MipsReginfo;
-  // MIPS .MIPS.options section defined by this file.
-  std::unique_ptr<MipsOptionsInputSection<ELFT>> MipsOptions;
   // MIPS .MIPS.abiflags section defined by this file.
   std::unique_ptr<MipsAbiFlagsInputSection<ELFT>> MipsAbiFlags;
 

Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=286397&r1=286396&r2=286397&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Wed Nov  9 15:36:56 2016
@@ -103,10 +103,8 @@ typename ELFT::uint InputSectionBase<ELF
     return Offset;
   case Merge:
     return cast<MergeInputSection<ELFT>>(this)->getOffset(Offset);
-  case MipsReginfo:
-  case MipsOptions:
   case MipsAbiFlags:
-    // MIPS .reginfo, .MIPS.options, and .MIPS.abiflags sections are consumed
+    // .MIPS.abiflags sections is consumed
     // by the linker, and the linker produces a single output section. It is
     // possible that input files contain section symbol points to the
     // corresponding input section. Redirect it to the produced output section.
@@ -801,59 +799,6 @@ template <class ELFT> void MergeInputSec
 }
 
 template <class ELFT>
-MipsReginfoInputSection<ELFT>::MipsReginfoInputSection(elf::ObjectFile<ELFT> *F,
-                                                       const Elf_Shdr *Hdr,
-                                                       StringRef Name)
-    : InputSectionBase<ELFT>(F, Hdr, Name,
-                             InputSectionBase<ELFT>::MipsReginfo) {
-  ArrayRef<uint8_t> Data = this->Data;
-  // Initialize this->Reginfo.
-  if (Data.size() != sizeof(Elf_Mips_RegInfo<ELFT>)) {
-    error(getName(this) + ": invalid size of .reginfo section");
-    return;
-  }
-  Reginfo = reinterpret_cast<const Elf_Mips_RegInfo<ELFT> *>(Data.data());
-  if (Config->Relocatable && Reginfo->ri_gp_value)
-    error(getName(this) + ": unsupported non-zero ri_gp_value");
-}
-
-template <class ELFT>
-bool MipsReginfoInputSection<ELFT>::classof(const InputSectionData *S) {
-  return S->kind() == InputSectionBase<ELFT>::MipsReginfo;
-}
-
-template <class ELFT>
-MipsOptionsInputSection<ELFT>::MipsOptionsInputSection(elf::ObjectFile<ELFT> *F,
-                                                       const Elf_Shdr *Hdr,
-                                                       StringRef Name)
-    : InputSectionBase<ELFT>(F, Hdr, Name,
-                             InputSectionBase<ELFT>::MipsOptions) {
-  // Find ODK_REGINFO option in the section's content.
-  ArrayRef<uint8_t> D = this->Data;
-  while (!D.empty()) {
-    if (D.size() < sizeof(Elf_Mips_Options<ELFT>)) {
-      error(getName(this) + ": invalid size of .MIPS.options section");
-      break;
-    }
-    auto *O = reinterpret_cast<const Elf_Mips_Options<ELFT> *>(D.data());
-    if (O->kind == ODK_REGINFO) {
-      Reginfo = &O->getRegInfo();
-      if (Config->Relocatable && Reginfo->ri_gp_value)
-        error(getName(this) + ": unsupported non-zero ri_gp_value");
-      break;
-    }
-    if (!O->size)
-      fatal(getName(this) + ": zero option descriptor size");
-    D = D.slice(O->size);
-  }
-}
-
-template <class ELFT>
-bool MipsOptionsInputSection<ELFT>::classof(const InputSectionData *S) {
-  return S->kind() == InputSectionBase<ELFT>::MipsOptions;
-}
-
-template <class ELFT>
 MipsAbiFlagsInputSection<ELFT>::MipsAbiFlagsInputSection(
     elf::ObjectFile<ELFT> *F, const Elf_Shdr *Hdr, StringRef Name)
     : InputSectionBase<ELFT>(F, Hdr, Name,
@@ -892,16 +837,6 @@ template class elf::MergeInputSection<EL
 template class elf::MergeInputSection<ELF64LE>;
 template class elf::MergeInputSection<ELF64BE>;
 
-template class elf::MipsReginfoInputSection<ELF32LE>;
-template class elf::MipsReginfoInputSection<ELF32BE>;
-template class elf::MipsReginfoInputSection<ELF64LE>;
-template class elf::MipsReginfoInputSection<ELF64BE>;
-
-template class elf::MipsOptionsInputSection<ELF32LE>;
-template class elf::MipsOptionsInputSection<ELF32BE>;
-template class elf::MipsOptionsInputSection<ELF64LE>;
-template class elf::MipsOptionsInputSection<ELF64BE>;
-
 template class elf::MipsAbiFlagsInputSection<ELF32LE>;
 template class elf::MipsAbiFlagsInputSection<ELF32BE>;
 template class elf::MipsAbiFlagsInputSection<ELF64LE>;

Modified: lld/trunk/ELF/InputSection.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.h?rev=286397&r1=286396&r2=286397&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.h (original)
+++ lld/trunk/ELF/InputSection.h Wed Nov  9 15:36:56 2016
@@ -39,7 +39,7 @@ template <class ELFT> class OutputSectio
 // section
 class InputSectionData {
 public:
-  enum Kind { Regular, EHFrame, Merge, MipsReginfo, MipsOptions, MipsAbiFlags };
+  enum Kind { Regular, EHFrame, Merge, MipsAbiFlags };
 
   // The garbage collector sets sections' Live bits.
   // If GC is disabled, all sections are considered live by default.
@@ -288,36 +288,6 @@ private:
 
 template <class ELFT> InputSection<ELFT> InputSection<ELFT>::Discarded;
 
-// MIPS .reginfo section provides information on the registers used by the code
-// in the object file. Linker should collect this information and write a single
-// .reginfo section in the output file. The output section contains a union of
-// used registers masks taken from input .reginfo sections and final value
-// of the `_gp` symbol.  For details: Chapter 4 / "Register Information" at
-// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
-template <class ELFT>
-class MipsReginfoInputSection : public InputSectionBase<ELFT> {
-  typedef typename ELFT::Shdr Elf_Shdr;
-
-public:
-  MipsReginfoInputSection(ObjectFile<ELFT> *F, const Elf_Shdr *Hdr,
-                          StringRef Name);
-  static bool classof(const InputSectionData *S);
-
-  const llvm::object::Elf_Mips_RegInfo<ELFT> *Reginfo = nullptr;
-};
-
-template <class ELFT>
-class MipsOptionsInputSection : public InputSectionBase<ELFT> {
-  typedef typename ELFT::Shdr Elf_Shdr;
-
-public:
-  MipsOptionsInputSection(ObjectFile<ELFT> *F, const Elf_Shdr *Hdr,
-                          StringRef Name);
-  static bool classof(const InputSectionData *S);
-
-  const llvm::object::Elf_Mips_RegInfo<ELFT> *Reginfo = nullptr;
-};
-
 template <class ELFT>
 class MipsAbiFlagsInputSection : public InputSectionBase<ELFT> {
   typedef typename ELFT::Shdr Elf_Shdr;

Modified: lld/trunk/ELF/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=286397&r1=286396&r2=286397&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Wed Nov  9 15:36:56 2016
@@ -913,6 +913,11 @@ OutputSection<ELFT>::OutputSection(Strin
     this->Entsize = sizeof(Elf_Rela);
   else if (Type == SHT_REL)
     this->Entsize = sizeof(Elf_Rel);
+  else if (Type == SHT_MIPS_REGINFO)
+    this->Entsize = sizeof(Elf_Mips_RegInfo<ELFT>);
+  else if (Type == SHT_MIPS_OPTIONS)
+    this->Entsize =
+        sizeof(Elf_Mips_Options<ELFT>) + sizeof(Elf_Mips_RegInfo<ELFT>);
 }
 
 template <class ELFT> void OutputSection<ELFT>::finalize() {
@@ -1725,64 +1730,6 @@ template <class ELFT> void VersionNeedSe
 }
 
 template <class ELFT>
-MipsReginfoOutputSection<ELFT>::MipsReginfoOutputSection()
-    : OutputSectionBase<ELFT>(".reginfo", SHT_MIPS_REGINFO, SHF_ALLOC) {
-  this->Addralign = 4;
-  this->Entsize = sizeof(Elf_Mips_RegInfo);
-  this->Size = sizeof(Elf_Mips_RegInfo);
-}
-
-template <class ELFT>
-void MipsReginfoOutputSection<ELFT>::writeTo(uint8_t *Buf) {
-  auto *R = reinterpret_cast<Elf_Mips_RegInfo *>(Buf);
-  if (Config->Relocatable)
-    R->ri_gp_value = 0;
-  else
-    R->ri_gp_value = Out<ELFT>::Got->Addr + MipsGPOffset;
-  R->ri_gprmask = GprMask;
-}
-
-template <class ELFT>
-void MipsReginfoOutputSection<ELFT>::addSection(InputSectionBase<ELFT> *C) {
-  // Copy input object file's .reginfo gprmask to output.
-  auto *S = cast<MipsReginfoInputSection<ELFT>>(C);
-  GprMask |= S->Reginfo->ri_gprmask;
-  S->OutSec = this;
-}
-
-template <class ELFT>
-MipsOptionsOutputSection<ELFT>::MipsOptionsOutputSection()
-    : OutputSectionBase<ELFT>(".MIPS.options", SHT_MIPS_OPTIONS,
-                              SHF_ALLOC | SHF_MIPS_NOSTRIP) {
-  this->Addralign = 8;
-  this->Entsize = 1;
-  this->Size = sizeof(Elf_Mips_Options) + sizeof(Elf_Mips_RegInfo);
-}
-
-template <class ELFT>
-void MipsOptionsOutputSection<ELFT>::writeTo(uint8_t *Buf) {
-  auto *Opt = reinterpret_cast<Elf_Mips_Options *>(Buf);
-  Opt->kind = ODK_REGINFO;
-  Opt->size = this->Size;
-  Opt->section = 0;
-  Opt->info = 0;
-  auto *Reg = reinterpret_cast<Elf_Mips_RegInfo *>(Buf + sizeof(*Opt));
-  if (Config->Relocatable)
-    Reg->ri_gp_value = 0;
-  else
-    Reg->ri_gp_value = Out<ELFT>::Got->Addr + MipsGPOffset;
-  Reg->ri_gprmask = GprMask;
-}
-
-template <class ELFT>
-void MipsOptionsOutputSection<ELFT>::addSection(InputSectionBase<ELFT> *C) {
-  auto *S = cast<MipsOptionsInputSection<ELFT>>(C);
-  if (S->Reginfo)
-    GprMask |= S->Reginfo->ri_gprmask;
-  S->OutSec = this;
-}
-
-template <class ELFT>
 MipsAbiFlagsOutputSection<ELFT>::MipsAbiFlagsOutputSection()
     : OutputSectionBase<ELFT>(".MIPS.abiflags", SHT_MIPS_ABIFLAGS, SHF_ALLOC) {
   this->Addralign = 8;
@@ -1876,12 +1823,6 @@ OutputSectionFactory<ELFT>::create(const
   case InputSectionBase<ELFT>::Merge:
     Sec = make<MergeOutputSection<ELFT>>(Key.Name, Type, Flags, Key.Alignment);
     break;
-  case InputSectionBase<ELFT>::MipsReginfo:
-    Sec = make<MipsReginfoOutputSection<ELFT>>();
-    break;
-  case InputSectionBase<ELFT>::MipsOptions:
-    Sec = make<MipsOptionsOutputSection<ELFT>>();
-    break;
   case InputSectionBase<ELFT>::MipsAbiFlags:
     Sec = make<MipsAbiFlagsOutputSection<ELFT>>();
     break;
@@ -1978,16 +1919,6 @@ template class EhOutputSection<ELF32BE>;
 template class EhOutputSection<ELF64LE>;
 template class EhOutputSection<ELF64BE>;
 
-template class MipsReginfoOutputSection<ELF32LE>;
-template class MipsReginfoOutputSection<ELF32BE>;
-template class MipsReginfoOutputSection<ELF64LE>;
-template class MipsReginfoOutputSection<ELF64BE>;
-
-template class MipsOptionsOutputSection<ELF32LE>;
-template class MipsOptionsOutputSection<ELF32BE>;
-template class MipsOptionsOutputSection<ELF64LE>;
-template class MipsOptionsOutputSection<ELF64BE>;
-
 template class MipsAbiFlagsOutputSection<ELF32LE>;
 template class MipsAbiFlagsOutputSection<ELF32BE>;
 template class MipsAbiFlagsOutputSection<ELF64LE>;

Modified: lld/trunk/ELF/OutputSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.h?rev=286397&r1=286396&r2=286397&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.h (original)
+++ lld/trunk/ELF/OutputSections.h Wed Nov  9 15:36:56 2016
@@ -31,7 +31,6 @@ template <class ELFT> class EhInputSecti
 template <class ELFT> class InputSection;
 template <class ELFT> class InputSectionBase;
 template <class ELFT> class MergeInputSection;
-template <class ELFT> class MipsReginfoInputSection;
 template <class ELFT> class OutputSection;
 template <class ELFT> class ObjectFile;
 template <class ELFT> class SharedFile;
@@ -57,8 +56,6 @@ public:
     GotPlt,
     HashTable,
     Merge,
-    MipsReginfo,
-    MipsOptions,
     MipsAbiFlags,
     Plt,
     Regular,
@@ -634,43 +631,6 @@ private:
 };
 
 template <class ELFT>
-class MipsReginfoOutputSection final : public OutputSectionBase<ELFT> {
-  typedef llvm::object::Elf_Mips_RegInfo<ELFT> Elf_Mips_RegInfo;
-  typedef OutputSectionBase<ELFT> Base;
-
-public:
-  MipsReginfoOutputSection();
-  void writeTo(uint8_t *Buf) override;
-  void addSection(InputSectionBase<ELFT> *S) override;
-  typename Base::Kind getKind() const override { return Base::MipsReginfo; }
-  static bool classof(const Base *B) {
-    return B->getKind() == Base::MipsReginfo;
-  }
-
-private:
-  uint32_t GprMask = 0;
-};
-
-template <class ELFT>
-class MipsOptionsOutputSection final : public OutputSectionBase<ELFT> {
-  typedef llvm::object::Elf_Mips_Options<ELFT> Elf_Mips_Options;
-  typedef llvm::object::Elf_Mips_RegInfo<ELFT> Elf_Mips_RegInfo;
-  typedef OutputSectionBase<ELFT> Base;
-
-public:
-  MipsOptionsOutputSection();
-  void writeTo(uint8_t *Buf) override;
-  void addSection(InputSectionBase<ELFT> *S) override;
-  typename Base::Kind getKind() const override { return Base::MipsOptions; }
-  static bool classof(const Base *B) {
-    return B->getKind() == Base::MipsOptions;
-  }
-
-private:
-  uint32_t GprMask = 0;
-};
-
-template <class ELFT>
 class MipsAbiFlagsOutputSection final : public OutputSectionBase<ELFT> {
   typedef llvm::object::Elf_Mips_ABIFlags<ELFT> Elf_Mips_ABIFlags;
   typedef OutputSectionBase<ELFT> Base;

Modified: lld/trunk/ELF/Relocations.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.cpp?rev=286397&r1=286396&r2=286397&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.cpp (original)
+++ lld/trunk/ELF/Relocations.cpp Wed Nov  9 15:36:56 2016
@@ -518,7 +518,7 @@ static typename ELFT::uint computeAddend
     if (Expr == R_GOTREL) {
       Addend -= MipsGPOffset;
       if (Body.isLocal())
-        Addend += File.getMipsGp0();
+        Addend += File.MipsGp0;
     }
   }
   if (Config->Pic && Config->EMachine == EM_PPC64 && Type == R_PPC64_TOC)

Modified: lld/trunk/ELF/SyntheticSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.cpp?rev=286397&r1=286396&r2=286397&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.cpp (original)
+++ lld/trunk/ELF/SyntheticSections.cpp Wed Nov  9 15:36:56 2016
@@ -22,6 +22,7 @@
 #include "OutputSections.h"
 #include "Strings.h"
 #include "SymbolTable.h"
+#include "Target.h"
 
 #include "lld/Core/Parallel.h"
 #include "llvm/Support/Endian.h"
@@ -76,6 +77,89 @@ template <class ELFT> InputSection<ELFT>
   return Ret;
 }
 
+// Iterate over sections of the specified type. For each section call
+// provided function. After that "kill" the section by turning off
+// "Live" flag, so that they won't be included in the final output.
+template <class ELFT>
+static void iterateSectionContents(
+    uint32_t Type,
+    std::function<void(ObjectFile<ELFT> *, ArrayRef<uint8_t>)> F) {
+  for (InputSectionBase<ELFT> *Sec : Symtab<ELFT>::X->Sections) {
+    if (Sec && Sec->Live && Sec->Type == Type) {
+      Sec->Live = false;
+      F(Sec->getFile(), Sec->Data);
+    }
+  }
+}
+
+// .MIPS.options section.
+template <class ELFT>
+MipsOptionsSection<ELFT>::MipsOptionsSection()
+    : InputSection<ELFT>(SHF_ALLOC, SHT_MIPS_OPTIONS, 8, ArrayRef<uint8_t>(),
+                         ".MIPS.options") {
+  Buf.resize(sizeof(Elf_Mips_Options) + sizeof(Elf_Mips_RegInfo));
+  getOptions()->kind = ODK_REGINFO;
+  getOptions()->size = Buf.size();
+  auto Func = [this](ObjectFile<ELFT> *F, ArrayRef<uint8_t> D) {
+    while (!D.empty()) {
+      if (D.size() < sizeof(Elf_Mips_Options)) {
+        error(getFilename(F) + ": invalid size of .MIPS.options section");
+        break;
+      }
+      auto *O = reinterpret_cast<const Elf_Mips_Options *>(D.data());
+      if (O->kind == ODK_REGINFO) {
+        if (Config->Relocatable && O->getRegInfo().ri_gp_value)
+          error(getFilename(F) + ": unsupported non-zero ri_gp_value");
+        getOptions()->getRegInfo().ri_gprmask |= O->getRegInfo().ri_gprmask;
+        F->MipsGp0 = O->getRegInfo().ri_gp_value;
+        break;
+      }
+      if (!O->size)
+        fatal(getFilename(F) + ": zero option descriptor size");
+      D = D.slice(O->size);
+    }
+  };
+  iterateSectionContents<ELFT>(SHT_MIPS_OPTIONS, Func);
+
+  this->Data = ArrayRef<uint8_t>(Buf);
+  // Section should be alive for N64 ABI only.
+  this->Live = ELFT::Is64Bits;
+}
+
+template <class ELFT> void MipsOptionsSection<ELFT>::finalize() {
+  if (!Config->Relocatable)
+    getOptions()->getRegInfo().ri_gp_value =
+        Out<ELFT>::Got->Addr + MipsGPOffset;
+}
+
+// MIPS .reginfo section.
+template <class ELFT>
+MipsReginfoSection<ELFT>::MipsReginfoSection()
+    : InputSection<ELFT>(SHF_ALLOC, SHT_MIPS_REGINFO, 4, ArrayRef<uint8_t>(),
+                         ".reginfo") {
+  auto Func = [this](ObjectFile<ELFT> *F, ArrayRef<uint8_t> D) {
+    if (D.size() != sizeof(Elf_Mips_RegInfo)) {
+      error(getFilename(F) + ": invalid size of .reginfo section");
+      return;
+    }
+    auto *R = reinterpret_cast<const Elf_Mips_RegInfo *>(D.data());
+    if (Config->Relocatable && R->ri_gp_value)
+      error(getFilename(F) + ": unsupported non-zero ri_gp_value");
+    Reginfo.ri_gprmask |= R->ri_gprmask;
+    F->MipsGp0 = R->ri_gp_value;
+  };
+  iterateSectionContents<ELFT>(SHT_MIPS_REGINFO, Func);
+
+  this->Data = ArrayRef<uint8_t>((const uint8_t *)&Reginfo, sizeof(Reginfo));
+  // Section should be alive for O32 and N32 ABIs only.
+  this->Live = !ELFT::Is64Bits;
+}
+
+template <class ELFT> void MipsReginfoSection<ELFT>::finalize() {
+  if (!Config->Relocatable)
+    Reginfo.ri_gp_value = Out<ELFT>::Got->Addr + MipsGPOffset;
+}
+
 static ArrayRef<uint8_t> createInterp() {
   // StringSaver guarantees that the returned string ends with '\0'.
   StringRef S = Saver.save(Config->DynamicLinker);
@@ -198,6 +282,16 @@ template InputSection<ELF32BE> *elf::cre
 template InputSection<ELF64LE> *elf::createInterpSection();
 template InputSection<ELF64BE> *elf::createInterpSection();
 
+template class elf::MipsOptionsSection<ELF32LE>;
+template class elf::MipsOptionsSection<ELF32BE>;
+template class elf::MipsOptionsSection<ELF64LE>;
+template class elf::MipsOptionsSection<ELF64BE>;
+
+template class elf::MipsReginfoSection<ELF32LE>;
+template class elf::MipsReginfoSection<ELF32BE>;
+template class elf::MipsReginfoSection<ELF64LE>;
+template class elf::MipsReginfoSection<ELF64BE>;
+
 template class elf::BuildIdSection<ELF32LE>;
 template class elf::BuildIdSection<ELF32BE>;
 template class elf::BuildIdSection<ELF64LE>;

Modified: lld/trunk/ELF/SyntheticSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.h?rev=286397&r1=286396&r2=286397&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.h (original)
+++ lld/trunk/ELF/SyntheticSections.h Wed Nov  9 15:36:56 2016
@@ -15,6 +15,37 @@
 namespace lld {
 namespace elf {
 
+// .MIPS.options section.
+template <class ELFT>
+class MipsOptionsSection final : public InputSection<ELFT> {
+  typedef llvm::object::Elf_Mips_Options<ELFT> Elf_Mips_Options;
+  typedef llvm::object::Elf_Mips_RegInfo<ELFT> Elf_Mips_RegInfo;
+
+public:
+  MipsOptionsSection();
+  void finalize();
+
+private:
+  std::vector<uint8_t> Buf;
+
+  Elf_Mips_Options *getOptions() {
+    return reinterpret_cast<Elf_Mips_Options *>(Buf.data());
+  }
+};
+
+// MIPS .reginfo section.
+template <class ELFT>
+class MipsReginfoSection final : public InputSection<ELFT> {
+  typedef llvm::object::Elf_Mips_RegInfo<ELFT> Elf_Mips_RegInfo;
+
+public:
+  MipsReginfoSection();
+  void finalize();
+
+private:
+  Elf_Mips_RegInfo Reginfo = {};
+};
+
 // .note.gnu.build-id section.
 template <class ELFT> class BuildIdSection : public InputSection<ELFT> {
 public:
@@ -74,11 +105,15 @@ template <class ELFT> struct In {
   static BuildIdSection<ELFT> *BuildId;
   static InputSection<ELFT> *Common;
   static InputSection<ELFT> *Interp;
+  static MipsOptionsSection<ELFT> *MipsOptions;
+  static MipsReginfoSection<ELFT> *MipsReginfo;
 };
 
 template <class ELFT> BuildIdSection<ELFT> *In<ELFT>::BuildId;
 template <class ELFT> InputSection<ELFT> *In<ELFT>::Common;
 template <class ELFT> InputSection<ELFT> *In<ELFT>::Interp;
+template <class ELFT> MipsOptionsSection<ELFT> *In<ELFT>::MipsOptions;
+template <class ELFT> MipsReginfoSection<ELFT> *In<ELFT>::MipsReginfo;
 
 } // namespace elf
 } // namespace lld

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=286397&r1=286396&r2=286397&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Wed Nov  9 15:36:56 2016
@@ -291,6 +291,21 @@ template <class ELFT> void Writer<ELFT>:
     In<ELFT>::Common = Common;
     Symtab<ELFT>::X->Sections.push_back(Common);
   }
+
+  if (Config->EMachine == EM_MIPS) {
+    // .MIPS.options
+    auto *OptSec = make<MipsOptionsSection<ELFT>>();
+    if (OptSec->Live) {
+      In<ELFT>::MipsOptions = OptSec;
+      Symtab<ELFT>::X->Sections.push_back(OptSec);
+    }
+    // MIPS .reginfo
+    auto *RegSec = make<MipsReginfoSection<ELFT>>();
+    if (RegSec->Live) {
+      In<ELFT>::MipsReginfo = RegSec;
+      Symtab<ELFT>::X->Sections.push_back(RegSec);
+    }
+  }
 }
 
 template <class ELFT>
@@ -1441,6 +1456,13 @@ static void sortARMExidx(uint8_t *Buf, u
 template <class ELFT> void Writer<ELFT>::writeSections() {
   uint8_t *Buf = Buffer->getBufferStart();
 
+  // Finalize MIPS .reginfo and .MIPS.options sections
+  // because they contain offsets to .got and _gp.
+  if (In<ELFT>::MipsReginfo)
+    In<ELFT>::MipsReginfo->finalize();
+  if (In<ELFT>::MipsOptions)
+    In<ELFT>::MipsOptions->finalize();
+
   // PPC64 needs to process relocations in the .opd section
   // before processing relocations in code-containing sections.
   Out<ELFT>::Opd = findSection(".opd");

Modified: lld/trunk/test/ELF/basic-mips.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/basic-mips.s?rev=286397&r1=286396&r2=286397&view=diff
==============================================================================
--- lld/trunk/test/ELF/basic-mips.s (original)
+++ lld/trunk/test/ELF/basic-mips.s Wed Nov  9 15:36:56 2016
@@ -57,23 +57,23 @@ __start:
 # CHECK-NEXT:   }
 # CHECK-NEXT:   Section {
 # CHECK-NEXT:     Index: 1
-# CHECK-NEXT:     Name: .reginfo
-# CHECK-NEXT:     Type: SHT_MIPS_REGINFO (0x70000006)
+# CHECK-NEXT:     Name: .MIPS.abiflags
+# CHECK-NEXT:     Type: SHT_MIPS_ABIFLAGS (0x7000002A)
 # CHECK-NEXT:     Flags [ (0x2)
 # CHECK-NEXT:       SHF_ALLOC (0x2)
 # CHECK-NEXT:     ]
-# CHECK-NEXT:     Address: 0x100F4
-# CHECK-NEXT:     Offset: 0xF4
+# CHECK-NEXT:     Address: 0x100F8
+# CHECK-NEXT:     Offset: 0xF8
 # CHECK-NEXT:     Size: 24
 # CHECK-NEXT:     Link: 0
 # CHECK-NEXT:     Info: 0
-# CHECK-NEXT:     AddressAlignment: 4
+# CHECK-NEXT:     AddressAlignment: 8
 # CHECK-NEXT:     EntrySize: 24
 # CHECK-NEXT:   }
 # CHECK-NEXT:   Section {
 # CHECK-NEXT:     Index: 2
-# CHECK-NEXT:     Name: .MIPS.abiflags
-# CHECK-NEXT:     Type: SHT_MIPS_ABIFLAGS (0x7000002A)
+# CHECK-NEXT:     Name: .reginfo
+# CHECK-NEXT:     Type: SHT_MIPS_REGINFO (0x70000006)
 # CHECK-NEXT:     Flags [ (0x2)
 # CHECK-NEXT:       SHF_ALLOC (0x2)
 # CHECK-NEXT:     ]
@@ -82,7 +82,7 @@ __start:
 # CHECK-NEXT:     Size: 24
 # CHECK-NEXT:     Link: 0
 # CHECK-NEXT:     Info: 0
-# CHECK-NEXT:     AddressAlignment: 8
+# CHECK-NEXT:     AddressAlignment: 4
 # CHECK-NEXT:     EntrySize: 24
 # CHECK-NEXT:   }
 # CHECK-NEXT:   Section {

Modified: lld/trunk/test/ELF/invalid/mips-invalid-options-descriptor.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/invalid/mips-invalid-options-descriptor.s?rev=286397&r1=286396&r2=286397&view=diff
==============================================================================
--- lld/trunk/test/ELF/invalid/mips-invalid-options-descriptor.s (original)
+++ lld/trunk/test/ELF/invalid/mips-invalid-options-descriptor.s Wed Nov  9 15:36:56 2016
@@ -2,4 +2,4 @@
 ## .MIPS.options with size of zero.
 # RUN: not ld.lld %p/Inputs/mips-invalid-options-descriptor.elf -o %t2 2>&1 | \
 # RUN:   FileCheck %s
-# CHECK: zero option descriptor size
+# CHECK: error: Invalid data was encountered while parsing the file

Removed: lld/trunk/test/ELF/invalid/mips-multiple-options.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/invalid/mips-multiple-options.test?rev=286396&view=auto
==============================================================================
--- lld/trunk/test/ELF/invalid/mips-multiple-options.test (original)
+++ lld/trunk/test/ELF/invalid/mips-multiple-options.test (removed)
@@ -1,25 +0,0 @@
-# RUN: yaml2obj %s -o %t
-# RUN: not ld.lld %t -o %tout 2>&1 | FileCheck %s
-
---- !ELF
-FileHeader:
-  Class:    ELFCLASS32
-  Data:     ELFDATA2LSB
-  Type:     ET_REL
-  Machine:  EM_MIPS
-  Flags:    [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-  - Name:          .o1
-    Type:          SHT_MIPS_OPTIONS
-    Flags:         [ SHF_ALLOC, SHF_EXECINSTR ]
-    AddressAlign:  16
-    Content:       "010000000000000000000000"
-
-  - Name:          .o2
-    Type:          SHT_MIPS_OPTIONS
-    Flags:         [ SHF_ALLOC, SHF_EXECINSTR ]
-    AddressAlign:  16
-    Content:       "010000000000000000000000"
-
-# CHECK: multiple SHT_MIPS_OPTIONS sections are not allowed

Removed: lld/trunk/test/ELF/invalid/mips-multiple-reginfo.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/invalid/mips-multiple-reginfo.test?rev=286396&view=auto
==============================================================================
--- lld/trunk/test/ELF/invalid/mips-multiple-reginfo.test (original)
+++ lld/trunk/test/ELF/invalid/mips-multiple-reginfo.test (removed)
@@ -1,25 +0,0 @@
-# RUN: yaml2obj %s -o %t
-# RUN: not ld.lld %t -o %tout 2>&1 | FileCheck %s
-
---- !ELF
-FileHeader:
-  Class:    ELFCLASS32
-  Data:     ELFDATA2LSB
-  Type:     ET_REL
-  Machine:  EM_MIPS
-  Flags:    [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-  - Name:          .foo1
-    Type:          SHT_MIPS_REGINFO
-    Flags:         [ SHF_ALLOC, SHF_EXECINSTR ]
-    AddressAlign:  16
-    Content:       "000000000000000000000000000000000000000000000000"
-
-  - Name:          .foo2
-    Type:          SHT_MIPS_REGINFO
-    Flags:         [ SHF_ALLOC, SHF_EXECINSTR ]
-    AddressAlign:  16
-    Content:       "000000000000000000000000000000000000000000000000"
-
-# CHECK: multiple SHT_MIPS_REGINFO sections are not allowed

Modified: lld/trunk/test/ELF/mips-gprel32-relocs-gp0.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/mips-gprel32-relocs-gp0.s?rev=286397&r1=286396&r2=286397&view=diff
==============================================================================
--- lld/trunk/test/ELF/mips-gprel32-relocs-gp0.s (original)
+++ lld/trunk/test/ELF/mips-gprel32-relocs-gp0.s Wed Nov  9 15:36:56 2016
@@ -31,7 +31,7 @@
 # DUMP: 00010004         .text          00000000 foo
 # DUMP: 00027ff0         .got           00000000 .hidden _gp
 
-# ERR: {{.*}}mips-gp0-non-zero.o(.reginfo): unsupported non-zero ri_gp_value
+# ERR: error: {{.*}}mips-gp0-non-zero.o: unsupported non-zero ri_gp_value
 
   .text
   .global  __start

Modified: lld/trunk/test/ELF/mips-n32-rels.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/mips-n32-rels.s?rev=286397&r1=286396&r2=286397&view=diff
==============================================================================
--- lld/trunk/test/ELF/mips-n32-rels.s (original)
+++ lld/trunk/test/ELF/mips-n32-rels.s Wed Nov  9 15:36:56 2016
@@ -38,7 +38,7 @@
 #                                                       ^-- %lo(0x17ff0)
 
 # CHECK:      Contents of section .rodata:
-# CHECK-NEXT:  10128 00020004
+# CHECK-NEXT:  10110 00020004
 #                    ^-- loc
 
 # CHECK: 00020004      .text   00000000 loc

Modified: lld/trunk/test/ELF/mips-options-r.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/mips-options-r.test?rev=286397&r1=286396&r2=286397&view=diff
==============================================================================
--- lld/trunk/test/ELF/mips-options-r.test (original)
+++ lld/trunk/test/ELF/mips-options-r.test Wed Nov  9 15:36:56 2016
@@ -1,7 +1,6 @@
 # Check that if input file contains .MIPS.options section and symbol
 # points to the section and the linker generates a relocatable output,
-# LLD does not crash and write section symbols point to the output
-# .MIPS.options section.
+# LLD does not crash.
 #
 # PR 27878
 #
@@ -12,8 +11,8 @@
 # % as -mabi=64 -mips64r2 t.s
 
 # RUN: ld.lld -r %p/Inputs/mips-options.o -o %t.o
-# RUN: llvm-readobj -t %t.o | FileCheck %s
+# RUN: llvm-readobj -s %t.o | FileCheck %s
 
 # REQUIRES: mips
 
-# CHECK: Section: .MIPS.options
+# CHECK: Name: .MIPS.options




More information about the llvm-commits mailing list