[lld] r256438 - Define a factory class to create output sections. NFC.

Rui Ueyama via llvm-commits llvm-commits at lists.llvm.org
Fri Dec 25 23:01:28 PST 2015


Author: ruiu
Date: Sat Dec 26 01:01:28 2015
New Revision: 256438

URL: http://llvm.org/viewvc/llvm-project?rev=256438&view=rev
Log:
Define a factory class to create output sections. NFC.

Previously, this code was directly written in createSections()
function. This patch moves some code out of that function to a
new class.

Modified:
    lld/trunk/ELF/Writer.cpp

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=256438&r1=256437&r2=256438&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Sat Dec 26 01:01:28 2015
@@ -44,10 +44,6 @@ private:
   void copyLocalSymbols();
   void createSections();
 
-  OutputSectionBase<ELFT> *createOutputSection(InputSectionBase<ELFT> *C,
-                                               StringRef Name, uintX_t Type,
-                                               uintX_t Flags);
-
   template <bool isRela>
   void scanRelocs(InputSectionBase<ELFT> &C,
                   iterator_range<const Elf_Rel_Impl<ELFT, isRela> *> Rels);
@@ -617,23 +613,85 @@ static bool includeInDynamicSymtab(const
   return B.isUsedInDynamicReloc();
 }
 
+// This class knows how to create an output section for a given
+// input section. Output section type is determined by various
+// factors, including input section's sh_flags, sh_type and
+// linker scripts.
+namespace {
+template <class ELFT> class OutputSectionFactory {
+  typedef typename ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
+  typedef typename ELFFile<ELFT>::uintX_t uintX_t;
+
+public:
+  std::pair<OutputSectionBase<ELFT> *, bool> create(InputSectionBase<ELFT> *C,
+                                                    StringRef OutsecName);
+
+  OutputSectionBase<ELFT> *lookup(StringRef Name, uint32_t Type, uintX_t Flags);
+
+private:
+  SectionKey<ELFT::Is64Bits> createKey(InputSectionBase<ELFT> *C,
+                                       StringRef OutsecName);
+  OutputSectionBase<ELFT> *createAux(InputSectionBase<ELFT> *C,
+                                     const SectionKey<ELFT::Is64Bits> &Key);
+
+  SmallDenseMap<SectionKey<ELFT::Is64Bits>, OutputSectionBase<ELFT> *> Map;
+};
+}
+
+template <class ELFT>
+std::pair<OutputSectionBase<ELFT> *, bool>
+OutputSectionFactory<ELFT>::create(InputSectionBase<ELFT> *C,
+                                   StringRef OutsecName) {
+  SectionKey<ELFT::Is64Bits> Key = createKey(C, OutsecName);
+  OutputSectionBase<ELFT> *&Sec = Map[Key];
+  if (Sec)
+    return {Sec, false};
+  Sec = createAux(C, Key);
+  return {Sec, true};
+}
+
 template <class ELFT>
 OutputSectionBase<ELFT> *
-Writer<ELFT>::createOutputSection(InputSectionBase<ELFT> *C, StringRef Name,
-                                  uintX_t Type, uintX_t Flags) {
+OutputSectionFactory<ELFT>::createAux(InputSectionBase<ELFT> *C,
+                                      const SectionKey<ELFT::Is64Bits> &Key) {
   switch (C->SectionKind) {
   case InputSectionBase<ELFT>::Regular:
-    return new OutputSection<ELFT>(Name, Type, Flags);
+    return new OutputSection<ELFT>(Key.Name, Key.Type, Key.Flags);
   case InputSectionBase<ELFT>::EHFrame:
-    return new EHOutputSection<ELFT>(Name, Type, Flags);
+    return new EHOutputSection<ELFT>(Key.Name, Key.Type, Key.Flags);
   case InputSectionBase<ELFT>::Merge:
-    return new MergeOutputSection<ELFT>(Name, Type, Flags);
+    return new MergeOutputSection<ELFT>(Key.Name, Key.Type, Key.Flags);
   case InputSectionBase<ELFT>::MipsReginfo:
     return new MipsReginfoOutputSection<ELFT>();
   }
   llvm_unreachable("Unknown output section type");
 }
 
+template <class ELFT>
+OutputSectionBase<ELFT> *OutputSectionFactory<ELFT>::lookup(StringRef Name,
+                                                            uint32_t Type,
+                                                            uintX_t Flags) {
+  return Map.lookup({Name, Type, Flags, 0});
+}
+
+template <class ELFT>
+SectionKey<ELFT::Is64Bits>
+OutputSectionFactory<ELFT>::createKey(InputSectionBase<ELFT> *C,
+                                      StringRef OutsecName) {
+  const Elf_Shdr *H = C->getSectionHdr();
+  uintX_t OutFlags = H->sh_flags & ~SHF_GROUP;
+
+  // For SHF_MERGE we create different output sections for each sh_entsize.
+  // This makes each output section simple and keeps a single level
+  // mapping from input to output.
+  uintX_t EntSize = isa<MergeInputSection<ELFT>>(C) ? H->sh_entsize : 0;
+  uint32_t OutType = H->sh_type;
+  if (OutType == SHT_PROGBITS && C->getSectionName() == ".eh_frame" &&
+      Config->EMachine == EM_X86_64)
+    OutType = SHT_X86_64_UNWIND;
+  return SectionKey<ELFT::Is64Bits>{OutsecName, OutType, OutFlags, EntSize};
+}
+
 // Create output section objects and add them to OutputSections.
 template <class ELFT> void Writer<ELFT>::createSections() {
   // .interp needs to be on the first page in the output file.
@@ -644,27 +702,18 @@ template <class ELFT> void Writer<ELFT>:
 
   std::vector<OutputSectionBase<ELFT> *> RegularSections;
 
+  OutputSectionFactory<ELFT> Factory;
   for (const std::unique_ptr<ObjectFile<ELFT>> &F : Symtab.getObjectFiles()) {
     for (InputSectionBase<ELFT> *C : F->getSections()) {
       if (isDiscarded(C)) {
         reportDiscarded(C, F);
         continue;
       }
-      const Elf_Shdr *H = C->getSectionHdr();
-      uintX_t OutFlags = H->sh_flags & ~SHF_GROUP;
-      // For SHF_MERGE we create different output sections for each sh_entsize.
-      // This makes each output section simple and keeps a single level
-      // mapping from input to output.
-      uintX_t EntSize = isa<MergeInputSection<ELFT>>(C) ? H->sh_entsize : 0;
-      uint32_t OutType = H->sh_type;
-      if (OutType == SHT_PROGBITS && C->getSectionName() == ".eh_frame" &&
-          Config->EMachine == EM_X86_64)
-        OutType = SHT_X86_64_UNWIND;
-      SectionKey<ELFT::Is64Bits> Key{getOutputSectionName(C->getSectionName()),
-                                     OutType, OutFlags, EntSize};
-      OutputSectionBase<ELFT> *&Sec = Map[Key];
-      if (!Sec) {
-        Sec = createOutputSection(C, Key.Name, Key.Type, Key.Flags);
+      OutputSectionBase<ELFT> *Sec;
+      bool IsNew;
+      std::tie(Sec, IsNew) =
+          Factory.create(C, getOutputSectionName(C->getSectionName()));
+      if (IsNew) {
         OwningSections.emplace_back(Sec);
         OutputSections.push_back(Sec);
         RegularSections.push_back(Sec);
@@ -674,14 +723,14 @@ template <class ELFT> void Writer<ELFT>:
   }
 
   Out<ELFT>::Bss = static_cast<OutputSection<ELFT> *>(
-      Map[{".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE, 0}]);
+      Factory.lookup(".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE));
 
-  Out<ELFT>::Dynamic->PreInitArraySec = Map.lookup(
-      {".preinit_array", SHT_PREINIT_ARRAY, SHF_WRITE | SHF_ALLOC, 0});
+  Out<ELFT>::Dynamic->PreInitArraySec = Factory.lookup(
+      ".preinit_array", SHT_PREINIT_ARRAY, SHF_WRITE | SHF_ALLOC);
   Out<ELFT>::Dynamic->InitArraySec =
-      Map.lookup({".init_array", SHT_INIT_ARRAY, SHF_WRITE | SHF_ALLOC, 0});
+      Factory.lookup(".init_array", SHT_INIT_ARRAY, SHF_WRITE | SHF_ALLOC);
   Out<ELFT>::Dynamic->FiniArraySec =
-      Map.lookup({".fini_array", SHT_FINI_ARRAY, SHF_WRITE | SHF_ALLOC, 0});
+      Factory.lookup(".fini_array", SHT_FINI_ARRAY, SHF_WRITE | SHF_ALLOC);
 
   auto AddStartEnd = [&](StringRef Start, StringRef End,
                          OutputSectionBase<ELFT> *OS) {
@@ -850,7 +899,7 @@ template <class ELFT> void Writer<ELFT>:
   // If we have a .opd section (used under PPC64 for function descriptors),
   // store a pointer to it here so that we can use it later when processing
   // relocations.
-  Out<ELFT>::Opd = Map.lookup({".opd", SHT_PROGBITS, SHF_WRITE | SHF_ALLOC, 0});
+  Out<ELFT>::Opd = Factory.lookup(".opd", SHT_PROGBITS, SHF_WRITE | SHF_ALLOC);
 }
 
 static bool isAlpha(char C) {




More information about the llvm-commits mailing list