Convert MipsOptionsSection to SyntheticSection.
authorRui Ueyama <ruiu@google.com>
Tue, 22 Nov 2016 04:13:09 +0000 (04:13 +0000)
committerRui Ueyama <ruiu@google.com>
Tue, 22 Nov 2016 04:13:09 +0000 (04:13 +0000)
llvm-svn: 287615

lld/ELF/SyntheticSections.cpp
lld/ELF/SyntheticSections.h
lld/ELF/Writer.cpp

index b0a5bd7..bb317c9 100644 (file)
@@ -112,21 +112,6 @@ template <class ELFT> MergeInputSection<ELFT> *elf::createCommentSection() {
   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(elf::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.abiflags section.
 template <class ELFT>
 MipsAbiFlagsSection<ELFT>::MipsAbiFlagsSection(Elf_Mips_ABIFlags Flags)
@@ -181,42 +166,62 @@ MipsAbiFlagsSection<ELFT> *MipsAbiFlagsSection<ELFT>::create() {
 
 // .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) {
+MipsOptionsSection<ELFT>::MipsOptionsSection(Elf_Mips_RegInfo Reginfo)
+    : SyntheticSection<ELFT>(SHF_ALLOC, SHT_MIPS_OPTIONS, 8, ".MIPS.options"),
+      Reginfo(Reginfo) {}
+
+template <class ELFT> void MipsOptionsSection<ELFT>::writeTo(uint8_t *Buf) {
+  auto *Options = reinterpret_cast<Elf_Mips_Options *>(Buf);
+  Options->kind = ODK_REGINFO;
+  Options->size = getSize();
+
+  if (!Config->Relocatable)
+    Reginfo.ri_gp_value = In<ELFT>::MipsGot->getVA() + MipsGPOffset;
+  memcpy(Buf + sizeof(Options), &Reginfo, sizeof(Reginfo));
+}
+
+template <class ELFT>
+MipsOptionsSection<ELFT> *MipsOptionsSection<ELFT>::create() {
+  // N64 ABI only.
+  if (!ELFT::Is64Bits)
+    return nullptr;
+
+  Elf_Mips_RegInfo Reginfo = {};
+  bool Create = false;
+
+  for (InputSectionBase<ELFT> *Sec : Symtab<ELFT>::X->Sections) {
+    if (!Sec->Live || Sec->Type != SHT_MIPS_OPTIONS)
+      continue;
+    Sec->Live = false;
+    Create = true;
+
+    std::string Filename = getFilename(Sec->getFile());
+    ArrayRef<uint8_t> D = Sec->Data;
+
     while (!D.empty()) {
       if (D.size() < sizeof(Elf_Mips_Options)) {
-        error(getFilename(F) + ": invalid size of .MIPS.options section");
+        error(Filename + ": 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;
+
+      auto *Opt = reinterpret_cast<const Elf_Mips_Options *>(D.data());
+      if (Opt->kind == ODK_REGINFO) {
+        if (Config->Relocatable && Opt->getRegInfo().ri_gp_value)
+          error(Filename + ": unsupported non-zero ri_gp_value");
+        Reginfo.ri_gprmask |= Opt->getRegInfo().ri_gprmask;
+        Sec->getFile()->MipsGp0 = Opt->getRegInfo().ri_gp_value;
         break;
       }
-      if (!O->size)
-        fatal(getFilename(F) + ": zero option descriptor size");
-      D = D.slice(O->size);
+
+      if (!Opt->size)
+        fatal(Filename + ": zero option descriptor size");
+      D = D.slice(Opt->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 =
-        In<ELFT>::MipsGot->getVA() + MipsGPOffset;
+  if (Create)
+    return new MipsOptionsSection<ELFT>(Reginfo);
+  return nullptr;
 }
 
 // MIPS .reginfo section.
index ac1f429..4e7e975 100644 (file)
 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());
-  }
-};
-
 template <class ELFT> class SyntheticSection : public InputSection<ELFT> {
   typedef typename ELFT::uint uintX_t;
 
@@ -580,6 +562,26 @@ private:
   Elf_Mips_ABIFlags Flags;
 };
 
+// .MIPS.options section.
+template <class ELFT>
+class MipsOptionsSection final : public SyntheticSection<ELFT> {
+  typedef llvm::object::Elf_Mips_Options<ELFT> Elf_Mips_Options;
+  typedef llvm::object::Elf_Mips_RegInfo<ELFT> Elf_Mips_RegInfo;
+
+public:
+  static MipsOptionsSection *create();
+
+  MipsOptionsSection(Elf_Mips_RegInfo Reginfo);
+  void writeTo(uint8_t *Buf) override;
+
+  size_t getSize() const override {
+    return sizeof(Elf_Mips_Options) + sizeof(Elf_Mips_RegInfo);
+  }
+
+private:
+  Elf_Mips_RegInfo Reginfo;
+};
+
 // MIPS .reginfo section.
 template <class ELFT>
 class MipsReginfoSection final : public SyntheticSection<ELFT> {
index b2bde2d..8667b9a 100644 (file)
@@ -312,10 +312,9 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() {
       Symtab<ELFT>::X->Sections.push_back(Sec);
     }
     // .MIPS.options
-    auto *OptSec = make<MipsOptionsSection<ELFT>>();
-    if (OptSec->Live) {
-      In<ELFT>::MipsOptions = OptSec;
-      Symtab<ELFT>::X->Sections.push_back(OptSec);
+    if (auto *Sec = MipsOptionsSection<ELFT>::create()) {
+      In<ELFT>::MipsOptions = Sec;
+      Symtab<ELFT>::X->Sections.push_back(Sec);
     }
     // MIPS .reginfo
     if (auto *Sec = MipsReginfoSection<ELFT>::create()) {